antigravity-mobile-proxy 0.1.6 → 0.1.7

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 (113) hide show
  1. package/.next/standalone/.next/app-path-routes-manifest.json +2 -0
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/routes-manifest.json +12 -0
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  6. package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  9. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  10. package/.next/standalone/.next/server/app/_not-found/page.js +5 -6
  11. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  12. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/api/v1/artifacts/active/route.js +5 -1
  14. package/.next/standalone/.next/server/app/api/v1/artifacts/active/route.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/api/v1/changes/active/route/app-paths-manifest.json +3 -0
  16. package/.next/standalone/.next/server/app/api/v1/changes/active/route/build-manifest.json +11 -0
  17. package/.next/standalone/.next/server/app/api/v1/changes/active/route/server-reference-manifest.json +4 -0
  18. package/.next/standalone/.next/server/app/api/v1/changes/active/route.js +11 -0
  19. package/.next/standalone/.next/server/app/api/v1/changes/active/route.js.map +5 -0
  20. package/.next/standalone/.next/server/app/api/v1/changes/active/route.js.nft.json +1 -0
  21. package/.next/standalone/.next/server/app/api/v1/changes/active/route_client-reference-manifest.js +2 -0
  22. package/.next/standalone/.next/server/app/api/v1/changes/diff/route/app-paths-manifest.json +3 -0
  23. package/.next/standalone/.next/server/app/api/v1/changes/diff/route/build-manifest.json +11 -0
  24. package/.next/standalone/.next/server/app/api/v1/changes/diff/route/server-reference-manifest.json +4 -0
  25. package/.next/standalone/.next/server/app/api/v1/changes/diff/route.js +7 -0
  26. package/.next/standalone/.next/server/app/api/v1/changes/diff/route.js.map +5 -0
  27. package/.next/standalone/.next/server/app/api/v1/changes/diff/route.js.nft.json +1 -0
  28. package/.next/standalone/.next/server/app/api/v1/changes/diff/route_client-reference-manifest.js +2 -0
  29. package/.next/standalone/.next/server/app/api/v1/chat/stream/route.js +1 -1
  30. package/.next/standalone/.next/server/app/api/v1/chat/stream/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/v1/windows/cdp-start/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/v1/windows/cdp-status/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/v1/windows/close/route.js +1 -1
  34. package/.next/standalone/.next/server/app/api/v1/windows/close/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/v1/windows/open/route.js +2 -2
  36. package/.next/standalone/.next/server/app/api/v1/windows/open/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/debug/page/build-manifest.json +3 -3
  38. package/.next/standalone/.next/server/app/debug/page.js +5 -5
  39. package/.next/standalone/.next/server/app/debug/page.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/debug/page_client-reference-manifest.js +1 -1
  41. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  42. package/.next/standalone/.next/server/app/page.js +5 -5
  43. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app-paths-manifest.json +2 -0
  46. package/.next/standalone/.next/server/chunks/[root-of-the-server]__26662154._.js +1 -1
  47. package/.next/standalone/.next/server/chunks/[root-of-the-server]__53c4f34d._.js +1 -1
  48. package/.next/standalone/.next/server/chunks/[root-of-the-server]__851f6b5a._.js +3 -0
  49. package/.next/standalone/.next/server/chunks/[root-of-the-server]__94275f7f._.js +1 -1
  50. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9a1969e6._.js +3 -0
  51. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c34d50c8._.js +1 -1
  52. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c696771d._.js +1 -1
  53. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d13bbe3c._.js +3 -0
  54. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d172e6aa._.js +3 -0
  55. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_v1_changes_active_route_actions_1bb9fc18.js +3 -0
  56. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_v1_changes_diff_route_actions_65d9ee16.js +3 -0
  57. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__d080cb3d._.js → [root-of-the-server]__012405ac._.js} +2 -2
  58. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a457c799._.js +3 -0
  59. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__f62d412e._.js → [root-of-the-server]__b9356576._.js} +2 -2
  60. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__52af585c._.js → [root-of-the-server]__ce78239f._.js} +2 -2
  61. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__ae6d24d9._.js → [root-of-the-server]__f47dc36d._.js} +2 -2
  62. package/.next/standalone/.next/server/chunks/ssr/{_524b2348._.js → _657ecbe9._.js} +3 -3
  63. package/.next/standalone/.next/server/chunks/ssr/{_fe4475aa._.js → _939145a4._.js} +3 -3
  64. package/.next/standalone/.next/server/chunks/ssr/app_layout_tsx_271801d7._.js +1 -1
  65. package/.next/standalone/.next/server/chunks/ssr/app_not-found_tsx_ef35050a._.js +1 -1
  66. package/.next/standalone/.next/server/chunks/ssr/components_chat-container_tsx_fcbc457f._.js +1 -1
  67. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_ece394eb.js +3 -0
  68. package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_39f173ba.js → node_modules_next_dist_esm_build_templates_app-page_7f45f9bf.js} +3 -3
  69. package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_f183c70b._.js → node_modules_next_dist_f21d913a._.js} +2 -2
  70. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  71. package/.next/standalone/.next/server/pages/500.html +2 -2
  72. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  74. package/.next/standalone/app/api/v1/artifacts/active/[filename]/route.ts +73 -23
  75. package/.next/standalone/app/api/v1/artifacts/active/route.ts +103 -52
  76. package/.next/standalone/app/api/v1/changes/active/route.ts +27 -0
  77. package/.next/standalone/app/api/v1/changes/diff/route.ts +119 -0
  78. package/.next/standalone/app/globals.css +424 -0
  79. package/.next/standalone/app/layout.tsx +3 -3
  80. package/.next/standalone/app/not-found.tsx +14 -23
  81. package/.next/standalone/components/artifact-panel.tsx +57 -13
  82. package/.next/standalone/components/changes-panel.tsx +178 -0
  83. package/.next/standalone/components/chat-container.tsx +44 -3
  84. package/.next/standalone/components/chat-input.tsx +44 -0
  85. package/.next/standalone/components/header.tsx +1 -13
  86. package/.next/standalone/hooks/use-changes.ts +61 -0
  87. package/.next/standalone/hooks/use-chat.ts +21 -3
  88. package/.next/standalone/hooks/use-conversations.ts +19 -11
  89. package/.next/standalone/lib/scraper/agent-state.ts +89 -54
  90. package/.next/standalone/lib/scraper/chat-history.ts +215 -85
  91. package/.next/standalone/lib/scraper/ide-artifacts.ts +212 -0
  92. package/.next/standalone/lib/scraper/ide-changes.ts +172 -0
  93. package/.next/standalone/lib/types.ts +11 -0
  94. package/.next/standalone/package-lock.json +2 -2
  95. package/.next/standalone/package.json +2 -2
  96. package/.next/standalone/scripts/check-send-button.js +126 -0
  97. package/.next/standalone/scripts/find-send-btn.js +65 -0
  98. package/.next/standalone/tsconfig.tsbuildinfo +1 -1
  99. package/.next/static/chunks/09dc2aa5c698c324.css +1 -0
  100. package/.next/static/chunks/{f7c83373e6561461.js → b9a0fabf54a78ef2.js} +1 -1
  101. package/.next/static/chunks/e2ccf5908cad5a88.js +5 -0
  102. package/.next/static/chunks/f7cc8fe5822bbc01.js +1 -0
  103. package/.next/static/chunks/{turbopack-3f34081d758747ed.js → turbopack-7b5dc393c5d3964b.js} +1 -1
  104. package/package.json +2 -2
  105. package/.next/standalone/.next/server/chunks/[root-of-the-server]__151eca3a._.js +0 -3
  106. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ec32b318._.js +0 -3
  107. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__f77eb371._.js +0 -3
  108. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_9170b7a0._.js +0 -3
  109. package/.next/standalone/app/global-error.tsx +0 -42
  110. package/.next/static/chunks/2317ab948a7d90a4.js +0 -5
  111. package/.next/static/chunks/2d277a81099566c3.js +0 -1
  112. package/.next/static/chunks/ad1121f40e497811.css +0 -1
  113. package/.next/static/chunks/d5d4abede4bc89fd.js +0 -1
@@ -75,6 +75,69 @@ html, body {
75
75
  @keyframes hitlSlideIn { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
76
76
  @keyframes typingBounce { 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; } 40% { transform: scale(1); opacity: 1; } }
77
77
  @keyframes wm-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
78
+ @keyframes shimmer {
79
+ 0% { background-position: -300px 0; }
80
+ 100% { background-position: 300px 0; }
81
+ }
82
+ @keyframes historyFadeIn {
83
+ from { opacity: 0; transform: translateY(16px); }
84
+ to { opacity: 1; transform: translateY(0); }
85
+ }
86
+
87
+ /* ── History Loading Skeleton ── */
88
+ .history-loading {
89
+ display: flex;
90
+ flex-direction: column;
91
+ gap: 18px;
92
+ padding: 20px 10px;
93
+ animation: historyFadeIn 0.4s ease-out;
94
+ max-width: 100%;
95
+ }
96
+ .history-loading-header {
97
+ display: flex;
98
+ align-items: center;
99
+ gap: 10px;
100
+ }
101
+ .history-loading-header.right {
102
+ justify-content: flex-end;
103
+ }
104
+ .history-loading-block {
105
+ display: flex;
106
+ flex-direction: column;
107
+ gap: 8px;
108
+ padding: 14px;
109
+ border-radius: var(--radius-md);
110
+ background: var(--agent-bubble);
111
+ border: 1px solid var(--border-subtle);
112
+ }
113
+ .skeleton-shimmer {
114
+ background: linear-gradient(
115
+ 90deg,
116
+ rgba(255, 255, 255, 0.03) 0%,
117
+ rgba(255, 255, 255, 0.08) 40%,
118
+ rgba(255, 255, 255, 0.03) 80%
119
+ );
120
+ background-size: 300px 100%;
121
+ animation: shimmer 1.6s ease-in-out infinite;
122
+ border-radius: 6px;
123
+ }
124
+ .skeleton-avatar {
125
+ width: 28px;
126
+ height: 28px;
127
+ border-radius: 50%;
128
+ flex-shrink: 0;
129
+ }
130
+ .skeleton-line {
131
+ height: 12px;
132
+ border-radius: 6px;
133
+ }
134
+ .history-loading-text {
135
+ text-align: center;
136
+ font-size: 12px;
137
+ color: var(--text-muted);
138
+ padding-top: 8px;
139
+ animation: pulse-dot 2s ease-in-out infinite;
140
+ }
78
141
 
79
142
  /* ══════════════════════════════════════════════
80
143
  MOBILE-FIRST BASE STYLES (< 480px)
@@ -594,6 +657,360 @@ html, body {
594
657
  .mode-icon { font-size: 12px; line-height: 1; }
595
658
  .mode-label { font-weight: 500; letter-spacing: 0.02em; }
596
659
 
660
+ /* ── Artifact Toggle Button (Input Toolbar) ── */
661
+ .artifact-toggle-btn {
662
+ display: flex;
663
+ align-items: center;
664
+ gap: 4px;
665
+ padding: 4px 8px;
666
+ border: 1px solid var(--border-subtle);
667
+ border-radius: var(--radius-xl);
668
+ background: var(--bg-secondary);
669
+ color: var(--text-secondary);
670
+ font-family: inherit;
671
+ font-size: 11px;
672
+ cursor: pointer;
673
+ transition: all var(--transition-smooth);
674
+ flex-shrink: 0;
675
+ white-space: nowrap;
676
+ user-select: none;
677
+ -webkit-tap-highlight-color: transparent;
678
+ min-height: 32px;
679
+ position: relative;
680
+ }
681
+ .artifact-toggle-btn:hover {
682
+ border-color: var(--border-active);
683
+ color: var(--text-primary);
684
+ transform: translateY(-1px);
685
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
686
+ }
687
+ .artifact-toggle-btn:active { transform: scale(0.95); }
688
+ .artifact-toggle-btn.active {
689
+ border-color: rgba(168, 85, 247, 0.4);
690
+ background: rgba(168, 85, 247, 0.1);
691
+ color: #c4b5fd;
692
+ }
693
+ .artifact-toggle-btn.active:hover {
694
+ border-color: rgba(168, 85, 247, 0.6);
695
+ background: rgba(168, 85, 247, 0.18);
696
+ color: #ddd6fe;
697
+ }
698
+ .artifact-badge {
699
+ display: inline-flex;
700
+ align-items: center;
701
+ justify-content: center;
702
+ min-width: 16px;
703
+ height: 16px;
704
+ padding: 0 4px;
705
+ border-radius: 99px;
706
+ background: rgba(168, 85, 247, 0.25);
707
+ color: #c4b5fd;
708
+ font-size: 9px;
709
+ font-weight: 700;
710
+ font-family: 'JetBrains Mono', monospace;
711
+ line-height: 1;
712
+ }
713
+ .artifact-toggle-btn.active .artifact-badge {
714
+ background: rgba(168, 85, 247, 0.35);
715
+ color: #e9d5ff;
716
+ }
717
+
718
+ /* ── Changes Toggle Button (Input Toolbar) ── */
719
+ .changes-toggle-btn {
720
+ display: flex;
721
+ align-items: center;
722
+ gap: 4px;
723
+ padding: 4px 8px;
724
+ border: 1px solid var(--border-subtle);
725
+ border-radius: var(--radius-xl);
726
+ background: var(--bg-secondary);
727
+ color: var(--text-secondary);
728
+ font-family: inherit;
729
+ font-size: 11px;
730
+ cursor: pointer;
731
+ transition: all var(--transition-smooth);
732
+ flex-shrink: 0;
733
+ white-space: nowrap;
734
+ user-select: none;
735
+ -webkit-tap-highlight-color: transparent;
736
+ min-height: 32px;
737
+ position: relative;
738
+ }
739
+ .changes-toggle-btn:hover {
740
+ border-color: var(--border-active);
741
+ color: var(--text-primary);
742
+ transform: translateY(-1px);
743
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
744
+ }
745
+ .changes-toggle-btn:active { transform: scale(0.95); }
746
+ .changes-toggle-btn.active {
747
+ border-color: rgba(52, 211, 153, 0.4);
748
+ background: rgba(52, 211, 153, 0.1);
749
+ color: #6ee7b7;
750
+ }
751
+ .changes-toggle-btn.active:hover {
752
+ border-color: rgba(52, 211, 153, 0.6);
753
+ background: rgba(52, 211, 153, 0.18);
754
+ color: #a7f3d0;
755
+ }
756
+ .changes-badge {
757
+ display: inline-flex;
758
+ align-items: center;
759
+ justify-content: center;
760
+ min-width: 16px;
761
+ height: 16px;
762
+ padding: 0 4px;
763
+ border-radius: 99px;
764
+ background: rgba(52, 211, 153, 0.25);
765
+ color: #6ee7b7;
766
+ font-size: 9px;
767
+ font-weight: 700;
768
+ font-family: 'JetBrains Mono', monospace;
769
+ line-height: 1;
770
+ }
771
+ .changes-toggle-btn.active .changes-badge {
772
+ background: rgba(52, 211, 153, 0.35);
773
+ color: #a7f3d0;
774
+ }
775
+
776
+ /* ── Changes Panel ── */
777
+ .changes-panel {
778
+ position: fixed;
779
+ top: 0;
780
+ right: 0;
781
+ width: 100%;
782
+ height: 100%;
783
+ background: var(--bg-primary);
784
+ z-index: 150;
785
+ transform: translateX(100%);
786
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
787
+ display: flex;
788
+ flex-direction: column;
789
+ overflow: hidden;
790
+ }
791
+ .changes-panel.open { transform: translateX(0); }
792
+ .changes-panel-header {
793
+ display: flex;
794
+ align-items: center;
795
+ gap: 10px;
796
+ padding: 14px 12px;
797
+ border-bottom: 1px solid var(--border-subtle);
798
+ background: var(--bg-secondary);
799
+ flex-shrink: 0;
800
+ }
801
+ .changes-panel-header h3 {
802
+ font-size: 15px;
803
+ font-weight: 600;
804
+ margin: 0;
805
+ color: var(--text-primary);
806
+ }
807
+ .changes-summary {
808
+ display: flex;
809
+ align-items: center;
810
+ justify-content: space-between;
811
+ padding: 10px 16px;
812
+ border-bottom: 1px solid var(--border-subtle);
813
+ background: rgba(52, 211, 153, 0.04);
814
+ }
815
+ .changes-count {
816
+ font-size: 12px;
817
+ font-weight: 600;
818
+ color: var(--text-primary);
819
+ font-family: 'JetBrains Mono', monospace;
820
+ }
821
+ .changes-stats {
822
+ display: flex;
823
+ gap: 8px;
824
+ }
825
+ .changes-additions {
826
+ color: var(--success);
827
+ font-size: 11px;
828
+ font-weight: 700;
829
+ font-family: 'JetBrains Mono', monospace;
830
+ }
831
+ .changes-deletions {
832
+ color: var(--error);
833
+ font-size: 11px;
834
+ font-weight: 700;
835
+ font-family: 'JetBrains Mono', monospace;
836
+ }
837
+ .changes-file-list {
838
+ flex: 1;
839
+ overflow-y: auto;
840
+ -webkit-overflow-scrolling: touch;
841
+ padding: 8px;
842
+ display: flex;
843
+ flex-direction: column;
844
+ gap: 4px;
845
+ }
846
+ .changes-file-item {
847
+ display: flex;
848
+ align-items: center;
849
+ gap: 10px;
850
+ padding: 10px 12px;
851
+ background: var(--bg-tertiary);
852
+ border: 1px solid var(--border-subtle);
853
+ border-radius: 6px;
854
+ min-height: 48px;
855
+ transition: all 0.2s ease;
856
+ cursor: pointer;
857
+ text-align: left;
858
+ font-family: inherit;
859
+ width: 100%;
860
+ -webkit-tap-highlight-color: transparent;
861
+ }
862
+ .changes-file-item:hover { border-color: var(--border-active); background: var(--bg-hover); }
863
+ .changes-file-item:active { transform: scale(0.98); }
864
+ .changes-file-icon { flex-shrink: 0; font-size: 14px; }
865
+ .changes-file-info { flex: 1; min-width: 0; overflow: hidden; }
866
+ .changes-file-name {
867
+ font-size: 13px;
868
+ font-weight: 500;
869
+ color: var(--text-primary);
870
+ overflow: hidden;
871
+ text-overflow: ellipsis;
872
+ white-space: nowrap;
873
+ }
874
+ .changes-file-path {
875
+ font-size: 10px;
876
+ color: var(--text-muted);
877
+ font-family: 'JetBrains Mono', monospace;
878
+ overflow: hidden;
879
+ text-overflow: ellipsis;
880
+ white-space: nowrap;
881
+ }
882
+ .changes-file-diff {
883
+ display: flex;
884
+ gap: 6px;
885
+ flex-shrink: 0;
886
+ }
887
+
888
+ /* ── Diff Viewer ── */
889
+ .diff-viewer {
890
+ display: flex;
891
+ flex-direction: column;
892
+ height: 100%;
893
+ overflow: hidden;
894
+ }
895
+ .diff-viewer-header {
896
+ display: flex;
897
+ align-items: center;
898
+ gap: 8px;
899
+ padding: 8px 12px;
900
+ border-bottom: 1px solid var(--border-subtle);
901
+ background: var(--bg-tertiary);
902
+ flex-shrink: 0;
903
+ overflow: hidden;
904
+ }
905
+ .diff-back-btn {
906
+ background: none;
907
+ border: none;
908
+ color: var(--accent-primary);
909
+ cursor: pointer;
910
+ font-size: 13px;
911
+ font-weight: 500;
912
+ padding: 2px 6px;
913
+ border-radius: 4px;
914
+ flex-shrink: 0;
915
+ }
916
+ .diff-back-btn:hover { background: rgba(99, 102, 241, 0.1); }
917
+ .diff-viewer-title {
918
+ font-size: 13px;
919
+ font-weight: 600;
920
+ color: var(--text-primary);
921
+ flex-shrink: 0;
922
+ }
923
+ .diff-viewer-path {
924
+ font-size: 10px;
925
+ font-family: 'JetBrains Mono', monospace;
926
+ color: var(--text-muted);
927
+ overflow: hidden;
928
+ text-overflow: ellipsis;
929
+ white-space: nowrap;
930
+ }
931
+ .diff-viewer-body {
932
+ flex: 1;
933
+ overflow-y: auto;
934
+ -webkit-overflow-scrolling: touch;
935
+ }
936
+ .diff-lines {
937
+ font-family: 'JetBrains Mono', monospace;
938
+ font-size: 11px;
939
+ line-height: 1.65;
940
+ }
941
+ .diff-line {
942
+ display: flex;
943
+ padding: 0 8px;
944
+ border-bottom: 1px solid transparent;
945
+ min-height: 20px;
946
+ }
947
+ .diff-line-num {
948
+ flex-shrink: 0;
949
+ width: 40px;
950
+ text-align: right;
951
+ padding-right: 8px;
952
+ color: var(--text-muted);
953
+ opacity: 0.5;
954
+ user-select: none;
955
+ }
956
+ .diff-line-indicator {
957
+ flex-shrink: 0;
958
+ width: 16px;
959
+ text-align: center;
960
+ font-weight: 700;
961
+ user-select: none;
962
+ }
963
+ .diff-line-content {
964
+ flex: 1;
965
+ white-space: pre-wrap;
966
+ word-break: break-all;
967
+ min-width: 0;
968
+ }
969
+
970
+ /* Line types */
971
+ .diff-line-add {
972
+ background: rgba(52, 211, 153, 0.08);
973
+ }
974
+ .diff-line-add .diff-line-indicator {
975
+ color: #34d399;
976
+ }
977
+ .diff-line-add .diff-line-content {
978
+ color: #a7f3d0;
979
+ }
980
+ .diff-line-del {
981
+ background: rgba(248, 113, 113, 0.08);
982
+ }
983
+ .diff-line-del .diff-line-indicator {
984
+ color: #f87171;
985
+ }
986
+ .diff-line-del .diff-line-content {
987
+ color: #fca5a5;
988
+ }
989
+ .diff-line-context .diff-line-content {
990
+ color: var(--text-secondary);
991
+ }
992
+ .diff-line-header {
993
+ background: rgba(99, 102, 241, 0.06);
994
+ border-bottom: 1px solid var(--border-subtle);
995
+ padding: 4px 8px;
996
+ margin-top: 4px;
997
+ }
998
+ .diff-line-header .diff-line-indicator {
999
+ color: var(--accent-primary);
1000
+ }
1001
+ .diff-line-header .diff-line-content {
1002
+ color: var(--accent-primary);
1003
+ font-weight: 500;
1004
+ }
1005
+ .diff-line-meta {
1006
+ background: rgba(100, 100, 120, 0.04);
1007
+ padding: 2px 8px;
1008
+ }
1009
+ .diff-line-meta .diff-line-content {
1010
+ color: var(--text-muted);
1011
+ font-style: italic;
1012
+ }
1013
+
597
1014
  /* ── Agent Selector ── */
598
1015
  .agent-selector-wrapper {
599
1016
  position: relative;
@@ -1090,6 +1507,13 @@ html, body {
1090
1507
  }
1091
1508
  .artifact-file-item:hover { border-color: var(--accent-primary); background: var(--bg-hover); }
1092
1509
  .artifact-file-item:active { transform: scale(0.98); }
1510
+ .artifact-file-item.non-file {
1511
+ cursor: default;
1512
+ opacity: 0.6;
1513
+ border-style: dashed;
1514
+ }
1515
+ .artifact-file-item.non-file:hover { border-color: var(--border-subtle); background: var(--bg-tertiary); }
1516
+ .artifact-file-item.non-file:active { transform: none; }
1093
1517
  .artifact-file-icon { color: var(--accent-primary); flex-shrink: 0; }
1094
1518
  .artifact-file-name { font-size: 13px; font-weight: 500; color: var(--text-primary); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1095
1519
  .artifact-file-size { font-size: 10px; font-family: 'JetBrains Mono', monospace; color: var(--text-muted); }
@@ -1,4 +1,4 @@
1
- import type { Metadata } from 'next';
1
+ import type { Metadata, Viewport } from 'next';
2
2
  import './globals.css';
3
3
 
4
4
  export const dynamic = 'force-dynamic';
@@ -8,11 +8,10 @@ export const metadata: Metadata = {
8
8
  description: 'Chat with the Antigravity AI Agent from any browser',
9
9
  };
10
10
 
11
- export const viewport = {
11
+ export const viewport: Viewport = {
12
12
  width: 'device-width',
13
13
  initialScale: 1,
14
14
  maximumScale: 1,
15
- viewportFit: 'cover' as const,
16
15
  themeColor: '#0a0a0f',
17
16
  };
18
17
 
@@ -24,6 +23,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
24
23
  href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
25
24
  rel="stylesheet"
26
25
  />
26
+ <meta name="viewport" content="viewport-fit=cover" />
27
27
  <meta name="apple-mobile-web-app-capable" content="yes" />
28
28
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
29
29
  </head>
@@ -1,27 +1,18 @@
1
- import type { Metadata } from 'next';
2
-
3
- export const metadata: Metadata = {
4
- title: '404 - Page Not Found',
5
- description: 'The page you are looking for does not exist.',
6
- };
7
-
8
1
  export default function GlobalNotFound() {
9
2
  return (
10
- <html lang="en">
11
- <body style={{
12
- display: 'flex',
13
- flexDirection: 'column' as const,
14
- alignItems: 'center',
15
- justifyContent: 'center',
16
- height: '100vh',
17
- backgroundColor: '#0a0a0f',
18
- color: '#888',
19
- fontFamily: 'system-ui, sans-serif',
20
- margin: 0,
21
- }}>
22
- <h1 style={{ fontSize: '3rem', margin: 0, color: '#fff' }}>404</h1>
23
- <p style={{ fontSize: '1.1rem', marginTop: '0.5rem' }}>Page not found</p>
24
- </body>
25
- </html>
3
+ <div style={{
4
+ display: 'flex',
5
+ flexDirection: 'column' as const,
6
+ alignItems: 'center',
7
+ justifyContent: 'center',
8
+ height: '100vh',
9
+ backgroundColor: '#0a0a0f',
10
+ color: '#888',
11
+ fontFamily: 'system-ui, sans-serif',
12
+ margin: 0,
13
+ }}>
14
+ <h1 style={{ fontSize: '3rem', margin: 0, color: '#fff' }}>404</h1>
15
+ <p style={{ fontSize: '1.1rem', marginTop: '0.5rem' }}>Page not found</p>
16
+ </div>
26
17
  );
27
18
  }
@@ -16,22 +16,35 @@ export default function ArtifactPanel({ open, onClose, activeConversation, files
16
16
  const [loading, setLoading] = useState(false);
17
17
 
18
18
  const formatSize = (bytes: number) => {
19
+ if (bytes <= 0) return '';
19
20
  if (bytes < 1024) return `${bytes}B`;
20
21
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
21
22
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
22
23
  };
23
24
 
24
25
  const formatTime = (mtime: string) => {
25
- const d = new Date(mtime);
26
- return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) + ' · ' + d.toLocaleDateString();
26
+ // Handle ISO dates
27
+ if (mtime.includes('T') || mtime.includes('-')) {
28
+ const d = new Date(mtime);
29
+ if (!isNaN(d.getTime())) {
30
+ return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) + ' · ' + d.toLocaleDateString();
31
+ }
32
+ }
33
+ // Already formatted (e.g., "Mar 10 11:21 PM") — pass through
34
+ return mtime;
27
35
  };
28
36
 
37
+ /** Open a file artifact (only for actual files with extensions) */
29
38
  const openFile = async (fileName: string) => {
30
- if (!activeConversation) return;
31
39
  setLoading(true);
32
40
  setViewingFile(fileName);
33
41
  try {
34
42
  const res = await fetch(`/api/v1/artifacts/active/${encodeURIComponent(fileName)}`);
43
+ if (!res.ok) {
44
+ const errorData = await res.json().catch(() => ({ error: 'Unknown error' }));
45
+ setFileContent(`Error: ${errorData.error || res.statusText}`);
46
+ return;
47
+ }
35
48
  const text = await res.text();
36
49
  setFileContent(text);
37
50
  } catch (e: any) {
@@ -41,12 +54,31 @@ export default function ArtifactPanel({ open, onClose, activeConversation, files
41
54
  }
42
55
  };
43
56
 
44
- const fileIcon = (name: string) => {
45
- if (name.endsWith('.md')) return '📄';
46
- if (name.endsWith('.json')) return '📋';
47
- if (name.endsWith('.ts') || name.endsWith('.tsx')) return '📘';
48
- if (name.endsWith('.css')) return '🎨';
49
- return '📁';
57
+ const isOpenable = (f: ArtifactFile) => {
58
+ // A file is openable if it has a file extension
59
+ return f.isFile !== false && /\.\w{1,5}$/.test(f.name);
60
+ };
61
+
62
+ const fileIcon = (f: ArtifactFile) => {
63
+ if (isOpenable(f)) {
64
+ const name = f.name;
65
+ if (name.endsWith('.md')) return '📄';
66
+ if (name.endsWith('.json')) return '📋';
67
+ if (name.endsWith('.ts') || name.endsWith('.tsx')) return '📘';
68
+ if (name.endsWith('.css')) return '🎨';
69
+ if (name.endsWith('.js') || name.endsWith('.jsx')) return '📜';
70
+ return '📄';
71
+ }
72
+ // Non-file artifact (IDE-managed, like screenshots, images, etc.)
73
+ return '🖼️';
74
+ };
75
+
76
+ const handleItemClick = (f: ArtifactFile) => {
77
+ if (isOpenable(f)) {
78
+ openFile(f.name);
79
+ }
80
+ // Non-file artifacts can't be opened in the proxy
81
+ // They are IDE-managed (screenshots, images, etc.)
50
82
  };
51
83
 
52
84
  return (
@@ -69,7 +101,13 @@ export default function ArtifactPanel({ open, onClose, activeConversation, files
69
101
  {activeConversation.title || 'Untitled'}
70
102
  </div>
71
103
  <div style={{ fontSize: '10px', fontFamily: "'JetBrains Mono', monospace", color: 'var(--text-muted)' }}>
72
- {files.length} file{files.length !== 1 ? 's' : ''}
104
+ {files.length} artifact{files.length !== 1 ? 's' : ''}
105
+ </div>
106
+ </div>
107
+ ) : files.length > 0 ? (
108
+ <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--border-subtle)', background: 'rgba(99,102,241,0.04)' }}>
109
+ <div style={{ fontSize: '10px', fontFamily: "'JetBrains Mono', monospace", color: 'var(--text-muted)' }}>
110
+ {files.length} artifact{files.length !== 1 ? 's' : ''}
73
111
  </div>
74
112
  </div>
75
113
  ) : (
@@ -112,8 +150,14 @@ export default function ArtifactPanel({ open, onClose, activeConversation, files
112
150
  ) : (
113
151
  <div className="artifact-file-list">
114
152
  {files.map(f => (
115
- <button key={f.name} className="artifact-file-item" onClick={() => openFile(f.name)}>
116
- <span className="artifact-file-icon">{fileIcon(f.name)}</span>
153
+ <button
154
+ key={f.name}
155
+ className={`artifact-file-item ${!isOpenable(f) ? 'non-file' : ''}`}
156
+ onClick={() => handleItemClick(f)}
157
+ disabled={!isOpenable(f)}
158
+ title={isOpenable(f) ? `Open ${f.name}` : `${f.name} (IDE artifact — view in Antigravity)`}
159
+ >
160
+ <span className="artifact-file-icon">{fileIcon(f)}</span>
117
161
  <div style={{ flex: 1, overflow: 'hidden' }}>
118
162
  <div className="artifact-file-name">{f.name}</div>
119
163
  <div style={{ fontSize: '10px', color: 'var(--text-muted)' }}>{formatTime(f.mtime)}</div>
@@ -121,7 +165,7 @@ export default function ArtifactPanel({ open, onClose, activeConversation, files
121
165
  <span className="artifact-file-size">{formatSize(f.size)}</span>
122
166
  </button>
123
167
  ))}
124
- {files.length === 0 && activeConversation && (
168
+ {files.length === 0 && (
125
169
  <div style={{ textAlign: 'center', padding: '24px', color: 'var(--text-muted)', fontSize: '13px' }}>
126
170
  No artifacts in this conversation
127
171
  </div>