@hanzo/browser-extension 1.9.31 → 1.9.34

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/browser-extension/background-firefox.js +1427 -0
  2. package/dist/browser-extension/background.js +1443 -18
  3. package/dist/browser-extension/chrome/background.js +1443 -18
  4. package/dist/browser-extension/chrome/manifest.json +17 -2
  5. package/dist/browser-extension/chrome/newtab.css +277 -0
  6. package/dist/browser-extension/chrome/newtab.html +13 -0
  7. package/dist/browser-extension/chrome/newtab.js +64 -0
  8. package/dist/browser-extension/chrome/popup.html +28 -0
  9. package/dist/browser-extension/chrome/popup.js +67 -1
  10. package/dist/browser-extension/firefox/background.js +1427 -0
  11. package/dist/browser-extension/firefox/manifest.json +10 -2
  12. package/dist/browser-extension/firefox/newtab.css +277 -0
  13. package/dist/browser-extension/firefox/newtab.html +13 -0
  14. package/dist/browser-extension/firefox/newtab.js +64 -0
  15. package/dist/browser-extension/firefox/popup.html +28 -0
  16. package/dist/browser-extension/firefox/popup.js +67 -1
  17. package/dist/browser-extension/manifest.json +17 -2
  18. package/dist/browser-extension/newtab.js +64 -0
  19. package/dist/browser-extension/popup.js +67 -1
  20. package/dist/browser-extension/safari/Info.plist +2 -2
  21. package/dist/browser-extension/safari/background.js +1443 -18
  22. package/dist/browser-extension/safari/newtab.css +277 -0
  23. package/dist/browser-extension/safari/newtab.html +13 -0
  24. package/dist/browser-extension/safari/newtab.js +64 -0
  25. package/dist/browser-extension/safari/popup.html +28 -0
  26. package/dist/browser-extension/safari/popup.js +67 -1
  27. package/package.json +3 -1
  28. package/src/answer/AnswerEngine.tsx +553 -0
  29. package/src/manifest-firefox.json +10 -2
  30. package/src/manifest.json +17 -2
  31. package/src/newtab.css +277 -0
  32. package/src/newtab.html +13 -0
  33. package/src/popup.html +28 -0
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Hanzo AI",
4
- "version": "1.9.31",
5
- "description": "AI-powered dev assistant — click-to-code navigation, source maps, WebGPU AI, and MCP integration for Claude Code.",
4
+ "version": "1.9.34",
5
+ "description": "AI answer engine, search, and dev assistant — Hanzo AI in a new tab, address-bar search, source-cited answers, realtime news, WebGPU AI, and MCP.",
6
6
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxfXGh0lPUT5m04GKfjUwrLsV6pLaK3VcZuFRPogqAir2tzyLYnQPRtHynue9yvDyguIVnlkwvcwfDOYZrvH76zbw4s6onPBG8HqTKO6LQ9K3kdO1qBBkMMjdOgULQ1MrWThEbpU7NSTiwLYpEta/jAvrKRCAeKIlQE8p6htZmPy9aRUZuae66JgLcAlzD2vviX9sVB1asFABJVswL1RgZ55/8IzZaUrFjzOo9OHK4hmEOtudzkML+5silsAYdC+1BZugph2x94ai17YmZTCL1XyUa5Ke4q80cj+i9rOTgzhZs+mruyhL/AvNVOXilsgqCdNqSz77naWzC3pVGbxOewIDAQAB",
7
7
  "permissions": [
8
8
  "activeTab",
@@ -19,6 +19,8 @@
19
19
  "host_permissions": [
20
20
  "http://localhost/*",
21
21
  "https://localhost/*",
22
+ "https://claude.ai/*",
23
+ "https://chatgpt.com/*",
22
24
  "<all_urls>"
23
25
  ],
24
26
  "content_security_policy": {
@@ -52,6 +54,19 @@
52
54
  "48": "icon48.png",
53
55
  "128": "icon128.png"
54
56
  },
57
+ "chrome_url_overrides": {
58
+ "newtab": "newtab.html"
59
+ },
60
+ "chrome_settings_overrides": {
61
+ "search_provider": {
62
+ "name": "Hanzo",
63
+ "keyword": "hanzo",
64
+ "search_url": "https://hanzo.chat/c/new?q={searchTerms}&submit=true",
65
+ "favicon_url": "https://hanzo.ai/favicon.ico",
66
+ "encoding": "UTF-8",
67
+ "is_default": true
68
+ }
69
+ },
55
70
  "web_accessible_resources": [
56
71
  {
57
72
  "resources": [
@@ -0,0 +1,277 @@
1
+ /* Hanzo Answer Engine — strict monochrome (brand primaryColor #FFFFFF).
2
+ Shared tokens mirror popup.css / sidebar.css. */
3
+ :root {
4
+ --bg: #0a0a0a;
5
+ --surface: #0f0f0f;
6
+ --surface-2: #171717;
7
+ --surface-3: #1e1e1e;
8
+ --text: #fafafa;
9
+ --text-2: #a3a3a3;
10
+ --text-3: #666666;
11
+ --border: rgba(255, 255, 255, 0.10);
12
+ --border-2: rgba(255, 255, 255, 0.16);
13
+ --glass: rgba(255, 255, 255, 0.04);
14
+ --glass-2: rgba(255, 255, 255, 0.07);
15
+ --radius: 12px;
16
+ --radius-sm: 8px;
17
+ --radius-xs: 6px;
18
+ --sidebar-w: 232px;
19
+ }
20
+
21
+ * { box-sizing: border-box; }
22
+
23
+ html, body {
24
+ margin: 0;
25
+ height: 100%;
26
+ background: var(--bg);
27
+ color: var(--text);
28
+ font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', sans-serif;
29
+ -webkit-font-smoothing: antialiased;
30
+ }
31
+
32
+ a { color: inherit; text-decoration: none; }
33
+
34
+ .ae-root {
35
+ display: grid;
36
+ grid-template-columns: var(--sidebar-w) 1fr;
37
+ height: 100vh;
38
+ transition: grid-template-columns 0.18s ease;
39
+ }
40
+ .ae-root.collapsed { grid-template-columns: 60px 1fr; }
41
+
42
+ /* ── Sidebar ─────────────────────────────────────────────── */
43
+ .ae-sidebar {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: 6px;
47
+ padding: 14px 12px;
48
+ border-right: 1px solid var(--border);
49
+ background: var(--surface);
50
+ min-width: 0;
51
+ }
52
+ .ae-side-top { display: flex; align-items: center; justify-content: space-between; }
53
+ .ae-brand {
54
+ display: flex; align-items: center; gap: 9px;
55
+ background: none; border: none; color: var(--text);
56
+ font-size: 15px; font-weight: 600; letter-spacing: -0.01em;
57
+ cursor: pointer; padding: 4px; min-width: 0;
58
+ }
59
+ .ae-brand span { white-space: nowrap; overflow: hidden; }
60
+ .ae-collapse, .ae-new, .ae-signin {
61
+ cursor: pointer; font-family: inherit;
62
+ }
63
+ .ae-collapse {
64
+ background: none; border: none; color: var(--text-3);
65
+ padding: 4px; border-radius: var(--radius-xs); display: flex;
66
+ }
67
+ .ae-collapse:hover { color: var(--text); background: var(--glass); }
68
+ .ae-new {
69
+ display: flex; align-items: center; gap: 8px;
70
+ margin-top: 8px; padding: 9px 12px;
71
+ background: var(--text); color: #000; border: none;
72
+ border-radius: var(--radius-sm); font-size: 13px; font-weight: 600;
73
+ white-space: nowrap; overflow: hidden;
74
+ }
75
+ .ae-new:hover { background: #fff; }
76
+ .ae-nav { display: flex; flex-direction: column; margin-top: 12px; gap: 1px; }
77
+ .ae-nav a {
78
+ padding: 8px 10px; border-radius: var(--radius-xs);
79
+ color: var(--text-2); font-size: 13px; white-space: nowrap;
80
+ }
81
+ .ae-nav a:hover { background: var(--glass); color: var(--text); }
82
+ .ae-side-bottom { margin-top: auto; }
83
+ .ae-signin {
84
+ width: 100%; padding: 9px 12px;
85
+ background: var(--glass-2); border: 1px solid var(--border);
86
+ color: var(--text); border-radius: var(--radius-sm);
87
+ font-size: 12.5px; font-weight: 500; white-space: nowrap; overflow: hidden;
88
+ }
89
+ .ae-signin:hover { border-color: var(--border-2); background: var(--surface-2); }
90
+ .ae-signin.big { width: auto; padding: 10px 18px; font-size: 14px; }
91
+ .collapsed .ae-brand span, .collapsed .ae-new span, .collapsed .ae-nav { display: none; }
92
+
93
+ /* ── Main ────────────────────────────────────────────────── */
94
+ .ae-main { min-width: 0; overflow: hidden; display: flex; flex-direction: column; }
95
+
96
+ /* Hero (empty state) */
97
+ .ae-hero {
98
+ flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
99
+ gap: 26px; padding: 24px; overflow-y: auto;
100
+ }
101
+ .ae-wordmark {
102
+ display: flex; align-items: center; gap: 14px;
103
+ font-size: 46px; font-weight: 600; letter-spacing: -0.03em; color: var(--text);
104
+ }
105
+ .ae-hero-card { width: 100%; max-width: 720px; }
106
+ .ae-news { width: 100%; max-width: 720px; }
107
+ .ae-news-head, .ae-followups-head, .ae-model-group-label {
108
+ font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
109
+ color: var(--text-3); margin-bottom: 10px;
110
+ }
111
+ .ae-news-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
112
+ .ae-news-item {
113
+ display: flex; flex-direction: column; gap: 4px;
114
+ padding: 11px 13px; border: 1px solid var(--border);
115
+ border-radius: var(--radius-sm); background: var(--surface);
116
+ }
117
+ .ae-news-item:hover { border-color: var(--border-2); background: var(--surface-2); }
118
+ .ae-news-title { font-size: 13px; color: var(--text); line-height: 1.35; }
119
+ .ae-news-meta { font-size: 11px; color: var(--text-3); }
120
+
121
+ /* ── Input card ──────────────────────────────────────────── */
122
+ .ae-card {
123
+ background: var(--surface-2);
124
+ border: 1px solid var(--border-2);
125
+ border-radius: var(--radius);
126
+ box-shadow: 0 8px 40px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.02);
127
+ overflow: hidden;
128
+ }
129
+ .ae-input {
130
+ display: block; width: 100%; resize: none;
131
+ padding: 16px 18px 6px; min-height: 30px; max-height: 200px;
132
+ background: transparent; border: none; outline: none;
133
+ color: var(--text); font-family: inherit; font-size: 15px; line-height: 1.5;
134
+ }
135
+ .ae-input::placeholder { color: var(--text-3); }
136
+ .ae-card-row {
137
+ display: flex; align-items: center; justify-content: space-between;
138
+ gap: 8px; padding: 8px 10px 10px; flex-wrap: wrap;
139
+ }
140
+ .ae-chips { display: flex; gap: 4px; flex-wrap: wrap; }
141
+ .ae-chip {
142
+ padding: 4px 9px; border-radius: 999px; cursor: pointer;
143
+ background: var(--glass); border: 1px solid var(--border);
144
+ color: var(--text-3); font-size: 11px; font-family: inherit;
145
+ }
146
+ .ae-chip:hover { color: var(--text-2); }
147
+ .ae-chip.on { background: var(--text); color: #000; border-color: var(--text); }
148
+ .ae-card-right { display: flex; align-items: center; gap: 6px; }
149
+ .ae-modes { display: flex; gap: 2px; background: var(--glass); border-radius: var(--radius-xs); padding: 2px; }
150
+ .ae-mode {
151
+ padding: 4px 9px; border: none; background: none; cursor: pointer;
152
+ color: var(--text-3); font-size: 11.5px; font-family: inherit; border-radius: 5px;
153
+ }
154
+ .ae-mode:hover { color: var(--text-2); }
155
+ .ae-mode.on { background: var(--surface-3); color: var(--text); }
156
+ .ae-send {
157
+ width: 34px; height: 34px; flex-shrink: 0; cursor: pointer;
158
+ display: flex; align-items: center; justify-content: center;
159
+ background: var(--text); color: #000; border: none; border-radius: 50%;
160
+ }
161
+ .ae-send:disabled { opacity: 0.4; cursor: default; }
162
+
163
+ /* ── Model picker ────────────────────────────────────────── */
164
+ .ae-picker { position: relative; }
165
+ .ae-picker-btn {
166
+ display: flex; align-items: center; gap: 6px; cursor: pointer;
167
+ padding: 6px 10px; background: var(--glass); border: 1px solid var(--border);
168
+ border-radius: var(--radius-xs); color: var(--text-2); font-size: 12px; font-family: inherit;
169
+ }
170
+ .ae-picker-btn:hover { color: var(--text); border-color: var(--border-2); }
171
+ .ae-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-2); }
172
+ .ae-picker-menu {
173
+ position: absolute; bottom: calc(100% + 6px); right: 0; z-index: 40;
174
+ width: 320px; max-height: 420px; display: flex; flex-direction: column;
175
+ background: var(--surface-2); border: 1px solid var(--border-2);
176
+ border-radius: var(--radius-sm); box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6); overflow: hidden;
177
+ }
178
+ .ae-picker-filter {
179
+ margin: 8px; padding: 8px 10px; background: var(--bg);
180
+ border: 1px solid var(--border); border-radius: var(--radius-xs);
181
+ color: var(--text); font-family: inherit; font-size: 13px; outline: none;
182
+ }
183
+ .ae-picker-list { overflow-y: auto; padding: 0 6px 6px; }
184
+ .ae-model-group-label { padding: 8px 8px 4px; margin: 0; }
185
+ .ae-model-row {
186
+ display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left;
187
+ padding: 8px 10px; background: none; border: none; cursor: pointer;
188
+ border-radius: var(--radius-xs); color: var(--text); font-family: inherit;
189
+ }
190
+ .ae-model-row:hover { background: var(--glass); }
191
+ .ae-model-row.active { background: var(--glass-2); }
192
+ .ae-model-name { font-size: 13px; display: flex; align-items: center; gap: 7px; }
193
+ .ae-model-desc { font-size: 11px; color: var(--text-3); line-height: 1.3; }
194
+ .ae-badge {
195
+ font-size: 9px; text-transform: uppercase; letter-spacing: 0.04em;
196
+ padding: 1px 5px; border-radius: 4px; background: var(--glass-2); color: var(--text-2);
197
+ }
198
+ .ae-plan-banner {
199
+ display: flex; align-items: center; justify-content: space-between; gap: 8px;
200
+ padding: 10px 12px; border-top: 1px solid var(--border);
201
+ font-size: 11.5px; color: var(--text-2); background: var(--surface);
202
+ }
203
+ .ae-plan-tiers { display: flex; gap: 8px; }
204
+ .ae-plan-tier b { color: var(--text); }
205
+
206
+ /* ── Answer view ─────────────────────────────────────────── */
207
+ .ae-answer-wrap { flex: 1; display: flex; flex-direction: column; min-height: 0; }
208
+ .ae-answer-scroll { flex: 1; overflow-y: auto; padding: 32px 28px 20px; }
209
+ .ae-answer-scroll > * { max-width: 760px; margin-left: auto; margin-right: auto; }
210
+ .ae-question { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 20px; }
211
+ .ae-sources { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 16px; margin-bottom: 8px; }
212
+ .ae-source {
213
+ flex: 0 0 190px; display: flex; flex-direction: column; gap: 6px;
214
+ padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm);
215
+ background: var(--surface);
216
+ }
217
+ .ae-source:hover { border-color: var(--border-2); background: var(--surface-2); }
218
+ .ae-source-head { display: flex; align-items: center; gap: 6px; }
219
+ .ae-source-head img { border-radius: 3px; }
220
+ .ae-source-host { font-size: 11px; color: var(--text-3); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
221
+ .ae-source-idx { font-size: 10px; color: var(--text-3); border: 1px solid var(--border); border-radius: 4px; padding: 0 5px; }
222
+ .ae-source-title { font-size: 12.5px; line-height: 1.35; color: var(--text); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
223
+
224
+ .ae-status { display: flex; align-items: center; gap: 10px; color: var(--text-2); font-size: 14px; padding: 8px 0; }
225
+
226
+ .ae-answer.markdown { font-size: 15px; line-height: 1.65; color: var(--text); }
227
+ .markdown h2 { font-size: 20px; margin: 22px 0 10px; font-weight: 600; }
228
+ .markdown h3 { font-size: 17px; margin: 18px 0 8px; font-weight: 600; }
229
+ .markdown h4, .markdown h5 { font-size: 15px; margin: 14px 0 6px; font-weight: 600; }
230
+ .markdown p { margin: 0 0 12px; }
231
+ .markdown ul, .markdown ol { margin: 0 0 12px; padding-left: 22px; }
232
+ .markdown li { margin: 4px 0; }
233
+ .markdown a { color: var(--text); text-decoration: underline; text-decoration-color: var(--text-3); text-underline-offset: 2px; }
234
+ .markdown a:hover { text-decoration-color: var(--text); }
235
+ .markdown code { background: var(--surface-2); padding: 1px 5px; border-radius: 4px; font-size: 0.9em; font-family: 'Geist Mono', ui-monospace, monospace; }
236
+
237
+ .ae-followups { margin-top: 26px; border-top: 1px solid var(--border); padding-top: 16px; }
238
+ .ae-followup {
239
+ display: flex; align-items: center; justify-content: space-between; width: 100%;
240
+ padding: 12px 4px; background: none; border: none; border-bottom: 1px solid var(--border);
241
+ color: var(--text); font-family: inherit; font-size: 14px; text-align: left; cursor: pointer;
242
+ }
243
+ .ae-followup:hover { color: var(--text); }
244
+ .ae-followup:hover .ae-followup-arrow { color: var(--text); transform: translateX(2px); }
245
+ .ae-followup-arrow { color: var(--text-3); transition: transform 0.12s ease; }
246
+
247
+ .ae-error { color: var(--text-2); padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
248
+ .ae-auth { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; padding: 8px 0; }
249
+ .ae-auth p { margin: 0; color: var(--text-2); font-size: 15px; }
250
+
251
+ .ae-answer-composer { padding: 12px 28px 20px; border-top: 1px solid var(--border); background: var(--bg); }
252
+ .ae-answer-composer > .ae-card { max-width: 760px; margin: 0 auto; }
253
+
254
+ /* ── Spinner ─────────────────────────────────────────────── */
255
+ .ae-spinner {
256
+ width: 14px; height: 14px; border-radius: 50%; display: inline-block;
257
+ border: 2px solid var(--border-2); border-top-color: var(--text);
258
+ animation: ae-spin 0.7s linear infinite;
259
+ }
260
+ @keyframes ae-spin { to { transform: rotate(360deg); } }
261
+
262
+ @media (max-width: 720px) {
263
+ .ae-root, .ae-root.collapsed { grid-template-columns: 1fr; }
264
+ .ae-sidebar { display: none; }
265
+ .ae-news-grid { grid-template-columns: 1fr; }
266
+ .ae-hero { gap: 20px; padding: 20px 16px; justify-content: flex-start; padding-top: 48px; }
267
+ .ae-wordmark { font-size: 34px; }
268
+ .ae-answer-scroll { padding: 20px 16px 16px; }
269
+ .ae-answer-composer { padding: 10px 16px 16px; }
270
+ .ae-question { font-size: 21px; }
271
+ /* Input card: let the control row wrap so the model picker + send stay
272
+ reachable at narrow widths (mobile-first). */
273
+ .ae-card-row { flex-direction: column; align-items: stretch; gap: 10px; }
274
+ .ae-card-right { justify-content: space-between; }
275
+ .ae-modes { flex: 1; justify-content: space-between; }
276
+ .ae-source { flex-basis: 150px; }
277
+ }
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Hanzo</title>
7
+ <link rel="stylesheet" href="newtab.css" />
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script src="newtab.js"></script>
12
+ </body>
13
+ </html>