neoagent 2.4.1-beta.21 → 2.4.1-beta.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.
Files changed (66) hide show
  1. package/extensions/chrome-browser/icons/logo.svg +21 -2
  2. package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  3. package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  4. package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  5. package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  6. package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  7. package/flutter_app/assets/branding/app_icon_1024.png +0 -0
  8. package/flutter_app/assets/branding/app_icon_128.png +0 -0
  9. package/flutter_app/assets/branding/app_icon_192.png +0 -0
  10. package/flutter_app/assets/branding/app_icon_256.png +0 -0
  11. package/flutter_app/assets/branding/app_icon_32.png +0 -0
  12. package/flutter_app/assets/branding/app_icon_512.png +0 -0
  13. package/flutter_app/assets/branding/app_icon_64.png +0 -0
  14. package/flutter_app/assets/branding/app_icon_light_1024.png +0 -0
  15. package/flutter_app/assets/branding/app_icon_light_128.png +0 -0
  16. package/flutter_app/assets/branding/app_icon_light_192.png +0 -0
  17. package/flutter_app/assets/branding/app_icon_light_256.png +0 -0
  18. package/flutter_app/assets/branding/app_icon_light_32.png +0 -0
  19. package/flutter_app/assets/branding/app_icon_light_512.png +0 -0
  20. package/flutter_app/assets/branding/app_icon_light_64.png +0 -0
  21. package/flutter_app/assets/branding/tray_icon_light_template.png +0 -0
  22. package/flutter_app/assets/branding/tray_icon_template.png +0 -0
  23. package/flutter_app/linux/runner/resources/app_icon.png +0 -0
  24. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  25. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  26. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  27. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  28. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  29. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  30. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  31. package/flutter_app/tool/generate_desktop_branding.py +170 -36
  32. package/flutter_app/web/favicon.png +0 -0
  33. package/flutter_app/web/favicon.svg +21 -2
  34. package/flutter_app/web/favicon_light.svg +21 -2
  35. package/flutter_app/web/icons/Icon-192-light.png +0 -0
  36. package/flutter_app/web/icons/Icon-192.png +0 -0
  37. package/flutter_app/web/icons/Icon-512-light.png +0 -0
  38. package/flutter_app/web/icons/Icon-512.png +0 -0
  39. package/flutter_app/web/icons/Icon-maskable-192-light.png +0 -0
  40. package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
  41. package/flutter_app/web/icons/Icon-maskable-512-light.png +0 -0
  42. package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
  43. package/flutter_app/windows/runner/main.cpp +7 -1
  44. package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
  45. package/package.json +1 -1
  46. package/server/public/.last_build_id +1 -1
  47. package/server/public/assets/assets/branding/app_icon_256.png +0 -0
  48. package/server/public/assets/assets/branding/app_icon_512.png +0 -0
  49. package/server/public/assets/assets/branding/app_icon_light_256.png +0 -0
  50. package/server/public/assets/assets/branding/app_icon_light_512.png +0 -0
  51. package/server/public/assets/assets/branding/tray_icon_light_template.png +0 -0
  52. package/server/public/assets/assets/branding/tray_icon_template.png +0 -0
  53. package/server/public/assets/web/icons/Icon-192.png +0 -0
  54. package/server/public/favicon.png +0 -0
  55. package/server/public/favicon.svg +21 -2
  56. package/server/public/favicon_light.svg +21 -2
  57. package/server/public/flutter_bootstrap.js +1 -1
  58. package/server/public/icons/Icon-192-light.png +0 -0
  59. package/server/public/icons/Icon-192.png +0 -0
  60. package/server/public/icons/Icon-512-light.png +0 -0
  61. package/server/public/icons/Icon-512.png +0 -0
  62. package/server/public/icons/Icon-maskable-192-light.png +0 -0
  63. package/server/public/icons/Icon-maskable-192.png +0 -0
  64. package/server/public/icons/Icon-maskable-512-light.png +0 -0
  65. package/server/public/icons/Icon-maskable-512.png +0 -0
  66. package/server/public/main.dart.js +4 -4
@@ -1,3 +1,22 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
2
- <image width="32" height="32" xlink:href="data:image/png;base64,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"/>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#9e8052"/>
5
+ <stop offset="100%" stop-color="#439081"/>
6
+ </linearGradient>
7
+ <radialGradient id="shine" cx="24%" cy="15%" r="70%">
8
+ <stop offset="0%" stop-color="#fff4d8" stop-opacity="0.24"/>
9
+ <stop offset="100%" stop-color="#fff4d8" stop-opacity="0"/>
10
+ </radialGradient>
11
+ </defs>
12
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1"/>
13
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#shine)"/>
14
+ <path d="M2.5 17h27v3.5c0 5-4 9-9 9h-9c-5 0-9-4-9-9Z" fill="#000000" opacity="0.08"/>
15
+ <rect x="3" y="3" width="26" height="26" rx="8.5" ry="8.5" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="1"/>
16
+ <path d="M16 6.25 26.15 12.3 16 16.3 5.85 12.3Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
17
+ <path d="M16 14.75 25.85 19.45 16 22.25 6.15 19.45Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
18
+ <path d="M16 20.45 24.85 24.75 16 26.85 7.15 24.75Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
19
+ <path d="M16 5.7 26.8 12.1 16 16.5 5.2 12.1Z" fill="#ffffff"/>
20
+ <path d="M16 14.2 26.5 19.3 16 22.4 5.5 19.3Z" fill="#ffffff"/>
21
+ <path d="M16 20 25.4 24.6 16 27 6.6 24.6Z" fill="#ffffff"/>
3
22
  </svg>
@@ -2,7 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import math
6
5
  from pathlib import Path
7
6
 
8
7
  from PIL import Image, ImageDraw, ImageFilter
@@ -18,9 +17,15 @@ LINUX_ICON_DIR = ROOT / "linux" / "runner" / "resources"
18
17
  ANDROID_RES_DIR = ROOT / "android" / "app" / "src" / "main" / "res"
19
18
  SERVER_PUBLIC_DIR = ROOT.parent / "server" / "public"
20
19
  SERVER_PUBLIC_ICONS_DIR = SERVER_PUBLIC_DIR / "icons"
21
-
22
- ACCENT = (143, 109, 62)
23
- ACCENT_ALT = (47, 125, 110)
20
+ STATIC_IMG_DIR = ROOT.parent / "static" / "img"
21
+ LANDING_LOGO_PATH = ROOT.parent / "landing" / "assets" / "logo.svg"
22
+ EXTENSION_LOGO_PATH = ROOT.parent / "extensions" / "chrome-browser" / "icons" / "logo.svg"
23
+
24
+ ACCENT = (104, 78, 44)
25
+ ACCENT_ALT = (35, 92, 82)
26
+ ACCENT_DARK = (158, 128, 82)
27
+ ACCENT_ALT_DARK = (67, 144, 129)
28
+ SYMBOL_LIGHT = (255, 247, 232, 255)
24
29
  WHITE = (255, 255, 255, 255)
25
30
  TRANSPARENT = (0, 0, 0, 0)
26
31
 
@@ -29,56 +34,83 @@ def lerp(a: float, b: float, t: float) -> float:
29
34
  return a + (b - a) * t
30
35
 
31
36
 
32
- def gradient_background(size: int) -> Image.Image:
37
+ def mix_channel(value: int, target: int, amount: float) -> int:
38
+ return max(0, min(255, round(lerp(value, target, amount))))
39
+
40
+
41
+ def mix_color(color: tuple[int, int, int], target: int, amount: float) -> tuple[int, int, int]:
42
+ return (
43
+ mix_channel(color[0], target, amount),
44
+ mix_channel(color[1], target, amount),
45
+ mix_channel(color[2], target, amount),
46
+ )
47
+
48
+
49
+ def gradient_background(
50
+ size: int,
51
+ start: tuple[int, int, int],
52
+ end: tuple[int, int, int],
53
+ ) -> Image.Image:
33
54
  img = Image.new("RGBA", (size, size), TRANSPARENT)
34
55
  px = img.load()
35
56
  for y in range(size):
36
57
  for x in range(size):
37
58
  tx = x / max(size - 1, 1)
38
59
  ty = y / max(size - 1, 1)
39
- t = (tx + ty) / 2
60
+ diagonal = (tx * 0.58) + (ty * 0.42)
61
+ glow = max(0.0, 1.0 - (((tx - 0.25) ** 2 + (ty - 0.18) ** 2) ** 0.5) / 0.58)
62
+ shade = max(0.0, 1.0 - (((tx - 0.86) ** 2 + (ty - 0.94) ** 2) ** 0.5) / 0.72)
63
+ t = min(1.0, max(0.0, diagonal + glow * 0.12 - shade * 0.08))
64
+ base = (
65
+ int(lerp(start[0], end[0], t)),
66
+ int(lerp(start[1], end[1], t)),
67
+ int(lerp(start[2], end[2], t)),
68
+ )
69
+ lit = mix_color(base, 255, glow * 0.14)
70
+ final = mix_color(lit, 0, shade * 0.16)
40
71
  px[x, y] = (
41
- int(lerp(ACCENT[0], ACCENT_ALT[0], t)),
42
- int(lerp(ACCENT[1], ACCENT_ALT[1], t)),
43
- int(lerp(ACCENT[2], ACCENT_ALT[2], t)),
72
+ final[0],
73
+ final[1],
74
+ final[2],
44
75
  255,
45
76
  )
46
77
  return img
47
78
 
48
79
 
49
- def logo_paths(size: int, padding_ratio: float = 0.18):
80
+ def logo_paths(size: int, padding_ratio: float = 0.16):
50
81
  pad = size * padding_ratio
51
82
  inner = size - pad * 2
52
83
  def point(x: float, y: float) -> tuple[float, float]:
53
84
  return (pad + inner * x, pad + inner * y)
54
85
 
55
- top = [point(0.5, 0.08), point(0.1, 0.3), point(0.5, 0.52), point(0.9, 0.3)]
56
- middle = [point(0.1, 0.52), point(0.5, 0.74), point(0.9, 0.52)]
57
- bottom = [point(0.1, 0.72), point(0.5, 0.94), point(0.9, 0.72)]
58
- return top, middle, bottom, inner
86
+ top = [point(0.5, 0.08), point(0.92, 0.35), point(0.5, 0.53), point(0.08, 0.35)]
87
+ middle = [point(0.5, 0.43), point(0.9, 0.64), point(0.5, 0.76), point(0.1, 0.64)]
88
+ bottom = [point(0.5, 0.67), point(0.86, 0.86), point(0.5, 0.96), point(0.14, 0.86)]
89
+ return top, middle, bottom
59
90
 
60
91
 
61
92
  def draw_logo(draw: ImageDraw.ImageDraw, size: int, color: tuple[int, int, int, int]) -> None:
62
- top, middle, bottom, inner = logo_paths(size)
63
- stroke = max(2, round(inner * 0.08))
93
+ top, middle, bottom = logo_paths(size)
64
94
  draw.polygon(top, fill=color)
65
- draw.line(middle, fill=color, width=stroke, joint="curve")
66
- draw.line(bottom, fill=color, width=stroke, joint="curve")
95
+ draw.polygon(middle, fill=color)
96
+ draw.polygon(bottom, fill=color)
67
97
 
68
98
 
69
- def make_app_icon(size: int) -> Image.Image:
99
+ def make_app_icon(size: int, *, light: bool = False) -> Image.Image:
70
100
  canvas = Image.new("RGBA", (size, size), TRANSPARENT)
101
+ start = ACCENT if light else ACCENT_DARK
102
+ end = ACCENT_ALT if light else ACCENT_ALT_DARK
103
+ symbol = SYMBOL_LIGHT if light else WHITE
71
104
 
72
105
  shadow = Image.new("RGBA", (size, size), TRANSPARENT)
73
106
  shadow_draw = ImageDraw.Draw(shadow)
74
- offset_y = size * 0.02
75
- corner = round(size * 0.34)
107
+ corner = round(size * 0.3)
76
108
  shadow_draw.rounded_rectangle(
77
- (size * 0.07, size * 0.07 + offset_y, size * 0.93, size * 0.93 + offset_y),
109
+ (size * 0.075, size * 0.09, size * 0.925, size * 0.94),
78
110
  radius=corner,
79
- fill=(0, 0, 0, 72),
111
+ fill=(0, 0, 0, 64 if light else 86),
80
112
  )
81
- shadow = shadow.filter(ImageFilter.GaussianBlur(radius=max(2, size * 0.04)))
113
+ shadow = shadow.filter(ImageFilter.GaussianBlur(radius=max(2, size * 0.035)))
82
114
  canvas.alpha_composite(shadow)
83
115
 
84
116
  base_mask = Image.new("L", (size, size), 0)
@@ -86,32 +118,92 @@ def make_app_icon(size: int) -> Image.Image:
86
118
  base_rect = (size * 0.08, size * 0.08, size * 0.92, size * 0.92)
87
119
  mask_draw.rounded_rectangle(base_rect, radius=corner, fill=255)
88
120
 
89
- base = gradient_background(size)
121
+ base = gradient_background(size, start, end)
90
122
  clipped = Image.new("RGBA", (size, size), TRANSPARENT)
91
123
  clipped.paste(base, mask=base_mask)
92
124
  canvas.alpha_composite(clipped)
93
125
 
126
+ shine = Image.new("RGBA", (size, size), TRANSPARENT)
127
+ shine_draw = ImageDraw.Draw(shine)
128
+ shine_draw.ellipse(
129
+ (size * -0.12, size * -0.18, size * 0.78, size * 0.58),
130
+ fill=(255, 255, 255, 30 if light else 42),
131
+ )
132
+ shine.putalpha(Image.composite(shine.getchannel("A"), Image.new("L", (size, size), 0), base_mask))
133
+ canvas.alpha_composite(shine)
134
+
135
+ lower_glaze = Image.new("RGBA", (size, size), TRANSPARENT)
136
+ lower_draw = ImageDraw.Draw(lower_glaze)
137
+ lower_draw.rounded_rectangle(
138
+ base_rect,
139
+ radius=corner,
140
+ fill=(0, 0, 0, 18 if light else 12),
141
+ )
142
+ lower_mask = Image.new("L", (size, size), 0)
143
+ lower_mask_draw = ImageDraw.Draw(lower_mask)
144
+ lower_mask_draw.rectangle((0, size * 0.55, size, size), fill=255)
145
+ lower_glaze.putalpha(Image.composite(lower_glaze.getchannel("A"), Image.new("L", (size, size), 0), lower_mask))
146
+ canvas.alpha_composite(lower_glaze)
147
+
94
148
  ring = Image.new("RGBA", (size, size), TRANSPARENT)
95
149
  ring_draw = ImageDraw.Draw(ring)
96
150
  ring_draw.rounded_rectangle(
97
151
  base_rect,
98
152
  radius=corner,
99
- outline=(255, 255, 255, 36),
153
+ outline=(255, 255, 255, 58 if light else 48),
100
154
  width=max(1, round(size * 0.012)),
101
155
  )
156
+ inset = size * 0.018
157
+ ring_draw.rounded_rectangle(
158
+ (
159
+ base_rect[0] + inset,
160
+ base_rect[1] + inset,
161
+ base_rect[2] - inset,
162
+ base_rect[3] - inset,
163
+ ),
164
+ radius=max(1, corner - round(inset)),
165
+ outline=(0, 0, 0, 26 if light else 20),
166
+ width=max(1, round(size * 0.006)),
167
+ )
102
168
  canvas.alpha_composite(ring)
103
169
 
170
+ glyph_shadow = Image.new("RGBA", (size, size), TRANSPARENT)
171
+ shadow_draw = ImageDraw.Draw(glyph_shadow)
172
+ draw_logo(shadow_draw, size, (0, 0, 0, 76 if light else 58))
173
+ glyph_shadow = glyph_shadow.transform(
174
+ glyph_shadow.size,
175
+ Image.Transform.AFFINE,
176
+ (1, 0, 0, 0, 1, size * 0.018),
177
+ resample=Image.Resampling.BICUBIC,
178
+ )
179
+ glyph_shadow = glyph_shadow.filter(ImageFilter.GaussianBlur(radius=max(1, size * 0.006)))
180
+ canvas.alpha_composite(glyph_shadow)
181
+
104
182
  glyph = Image.new("RGBA", (size, size), TRANSPARENT)
105
183
  draw = ImageDraw.Draw(glyph)
106
- draw_logo(draw, size, WHITE)
184
+ draw_logo(draw, size, symbol)
107
185
  canvas.alpha_composite(glyph)
186
+
187
+ glyph_highlight = Image.new("RGBA", (size, size), TRANSPARENT)
188
+ highlight_draw = ImageDraw.Draw(glyph_highlight)
189
+ draw_logo(highlight_draw, size, (255, 255, 255, 26 if light else 34))
190
+ glyph_highlight = glyph_highlight.transform(
191
+ glyph_highlight.size,
192
+ Image.Transform.AFFINE,
193
+ (1, 0, 0, 0, 1, -size * 0.012),
194
+ resample=Image.Resampling.BICUBIC,
195
+ )
196
+ canvas.alpha_composite(glyph_highlight)
108
197
  return canvas
109
198
 
110
199
 
111
- def make_tray_template(size: int = 64) -> Image.Image:
200
+ def make_tray_template(
201
+ size: int = 64,
202
+ color: tuple[int, int, int, int] = (0, 0, 0, 255),
203
+ ) -> Image.Image:
112
204
  img = Image.new("RGBA", (size, size), TRANSPARENT)
113
205
  draw = ImageDraw.Draw(img)
114
- draw_logo(draw, size, (0, 0, 0, 255))
206
+ draw_logo(draw, size, color)
115
207
  return img
116
208
 
117
209
 
@@ -121,6 +213,9 @@ def ensure_dirs() -> None:
121
213
  MAC_ICON_DIR.mkdir(parents=True, exist_ok=True)
122
214
  LINUX_ICON_DIR.mkdir(parents=True, exist_ok=True)
123
215
  SERVER_PUBLIC_ICONS_DIR.mkdir(parents=True, exist_ok=True)
216
+ STATIC_IMG_DIR.mkdir(parents=True, exist_ok=True)
217
+ LANDING_LOGO_PATH.parent.mkdir(parents=True, exist_ok=True)
218
+ EXTENSION_LOGO_PATH.parent.mkdir(parents=True, exist_ok=True)
124
219
 
125
220
 
126
221
  def write_text(path: Path, content: str) -> None:
@@ -132,18 +227,36 @@ def copy_png(image: Image.Image, path: Path, size: int) -> None:
132
227
  save_png(image, path, size)
133
228
 
134
229
 
135
- def write_favicon_svg(path: Path) -> None:
230
+ def write_favicon_svg(path: Path, *, light: bool = False) -> None:
231
+ start = ACCENT if light else ACCENT_DARK
232
+ end = ACCENT_ALT if light else ACCENT_ALT_DARK
233
+ symbol = "#fff9ed" if light else "#ffffff"
234
+ stroke = "#000000" if light else "#ffffff"
235
+ stroke_opacity = "0.24" if light else "0.16"
236
+ glow = "#ffffff" if light else "#fff4d8"
237
+ top_opacity = "0.20" if light else "0.24"
238
+ shade_opacity = "0.12" if light else "0.08"
136
239
  svg = f"""<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
137
240
  <defs>
138
241
  <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
139
- <stop offset="0%" stop-color="#{ACCENT[0]:02x}{ACCENT[1]:02x}{ACCENT[2]:02x}"/>
140
- <stop offset="100%" stop-color="#{ACCENT_ALT[0]:02x}{ACCENT_ALT[1]:02x}{ACCENT_ALT[2]:02x}"/>
242
+ <stop offset="0%" stop-color="#{start[0]:02x}{start[1]:02x}{start[2]:02x}"/>
243
+ <stop offset="100%" stop-color="#{end[0]:02x}{end[1]:02x}{end[2]:02x}"/>
141
244
  </linearGradient>
245
+ <radialGradient id="shine" cx="24%" cy="15%" r="70%">
246
+ <stop offset="0%" stop-color="{glow}" stop-opacity="{top_opacity}"/>
247
+ <stop offset="100%" stop-color="{glow}" stop-opacity="0"/>
248
+ </radialGradient>
142
249
  </defs>
143
- <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1"/>
144
- <polygon points="16,5.7 5.2,11.6 16,17.6 26.8,11.6" fill="white"/>
145
- <polyline points="5.2,17.6 16,23.5 26.8,17.6" fill="none" stroke="white" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
146
- <polyline points="5.2,22.7 16,28.1 26.8,22.7" fill="none" stroke="white" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
250
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="{stroke}" stroke-opacity="{stroke_opacity}" stroke-width="1"/>
251
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#shine)"/>
252
+ <path d="M2.5 17h27v3.5c0 5-4 9-9 9h-9c-5 0-9-4-9-9Z" fill="#000000" opacity="{shade_opacity}"/>
253
+ <rect x="3" y="3" width="26" height="26" rx="8.5" ry="8.5" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="1"/>
254
+ <path d="M16 6.25 26.15 12.3 16 16.3 5.85 12.3Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
255
+ <path d="M16 14.75 25.85 19.45 16 22.25 6.15 19.45Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
256
+ <path d="M16 20.45 24.85 24.75 16 26.85 7.15 24.75Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
257
+ <path d="M16 5.7 26.8 12.1 16 16.5 5.2 12.1Z" fill="{symbol}"/>
258
+ <path d="M16 14.2 26.5 19.3 16 22.4 5.5 19.3Z" fill="{symbol}"/>
259
+ <path d="M16 20 25.4 24.6 16 27 6.6 24.6Z" fill="{symbol}"/>
147
260
  </svg>
148
261
  """
149
262
  write_text(path, svg)
@@ -156,6 +269,7 @@ def save_png(image: Image.Image, path: Path, size: int) -> None:
156
269
  def main() -> None:
157
270
  ensure_dirs()
158
271
  master = make_app_icon(1024)
272
+ light_master = make_app_icon(1024, light=True)
159
273
 
160
274
  save_png(master, BRANDING_DIR / "app_icon_1024.png", 1024)
161
275
  save_png(master, BRANDING_DIR / "app_icon_512.png", 512)
@@ -164,9 +278,18 @@ def main() -> None:
164
278
  save_png(master, BRANDING_DIR / "app_icon_128.png", 128)
165
279
  save_png(master, BRANDING_DIR / "app_icon_64.png", 64)
166
280
  save_png(master, BRANDING_DIR / "app_icon_32.png", 32)
281
+ save_png(light_master, BRANDING_DIR / "app_icon_light_1024.png", 1024)
282
+ save_png(light_master, BRANDING_DIR / "app_icon_light_512.png", 512)
283
+ save_png(light_master, BRANDING_DIR / "app_icon_light_256.png", 256)
284
+ save_png(light_master, BRANDING_DIR / "app_icon_light_192.png", 192)
285
+ save_png(light_master, BRANDING_DIR / "app_icon_light_128.png", 128)
286
+ save_png(light_master, BRANDING_DIR / "app_icon_light_64.png", 64)
287
+ save_png(light_master, BRANDING_DIR / "app_icon_light_32.png", 32)
167
288
 
168
289
  tray = make_tray_template(64)
169
290
  save_png(tray, BRANDING_DIR / "tray_icon_template.png", 64)
291
+ light_tray = make_tray_template(64, WHITE)
292
+ save_png(light_tray, BRANDING_DIR / "tray_icon_light_template.png", 64)
170
293
 
171
294
  icon_sizes = {
172
295
  16: "app_icon_16.png",
@@ -196,13 +319,24 @@ def main() -> None:
196
319
  for size, filename in web_icon_sizes.items():
197
320
  copy_png(master, WEB_ICONS_DIR / filename, size)
198
321
  copy_png(master, WEB_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-"), size)
322
+ copy_png(light_master, WEB_ICONS_DIR / filename.replace(".png", "-light.png"), size)
323
+ copy_png(light_master, WEB_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-").replace(".png", "-light.png"), size)
199
324
  copy_png(master, SERVER_PUBLIC_ICONS_DIR / filename, size)
200
325
  copy_png(master, SERVER_PUBLIC_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-"), size)
201
326
 
202
327
  copy_png(master, WEB_DIR / "favicon.png", 32)
203
328
  copy_png(master, SERVER_PUBLIC_DIR / "favicon.png", 32)
204
329
  write_favicon_svg(WEB_DIR / "favicon.svg")
330
+ write_favicon_svg(WEB_DIR / "favicon_light.svg", light=True)
205
331
  write_favicon_svg(SERVER_PUBLIC_DIR / "favicon.svg")
332
+ write_favicon_svg(SERVER_PUBLIC_DIR / "favicon_light.svg", light=True)
333
+ write_favicon_svg(LANDING_LOGO_PATH, light=True)
334
+ write_favicon_svg(EXTENSION_LOGO_PATH)
335
+ copy_png(master, STATIC_IMG_DIR / "app_icon.png", 512)
336
+ copy_png(light_master, STATIC_IMG_DIR / "app_icon_light.png", 512)
337
+ copy_png(master, SERVER_PUBLIC_DIR / "assets" / "assets" / "branding" / "app_icon_256.png", 256)
338
+ copy_png(tray, SERVER_PUBLIC_DIR / "assets" / "assets" / "branding" / "tray_icon_template.png", 64)
339
+ copy_png(master, SERVER_PUBLIC_DIR / "assets" / "web" / "icons" / "Icon-192.png", 192)
206
340
 
207
341
  android_icon_sizes = {
208
342
  "mipmap-mdpi": 48,
Binary file
@@ -1,3 +1,22 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
2
- <image width="32" height="32" xlink:href="data:image/png;base64,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"/>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#9e8052"/>
5
+ <stop offset="100%" stop-color="#439081"/>
6
+ </linearGradient>
7
+ <radialGradient id="shine" cx="24%" cy="15%" r="70%">
8
+ <stop offset="0%" stop-color="#fff4d8" stop-opacity="0.24"/>
9
+ <stop offset="100%" stop-color="#fff4d8" stop-opacity="0"/>
10
+ </radialGradient>
11
+ </defs>
12
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1"/>
13
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#shine)"/>
14
+ <path d="M2.5 17h27v3.5c0 5-4 9-9 9h-9c-5 0-9-4-9-9Z" fill="#000000" opacity="0.08"/>
15
+ <rect x="3" y="3" width="26" height="26" rx="8.5" ry="8.5" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="1"/>
16
+ <path d="M16 6.25 26.15 12.3 16 16.3 5.85 12.3Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
17
+ <path d="M16 14.75 25.85 19.45 16 22.25 6.15 19.45Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
18
+ <path d="M16 20.45 24.85 24.75 16 26.85 7.15 24.75Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
19
+ <path d="M16 5.7 26.8 12.1 16 16.5 5.2 12.1Z" fill="#ffffff"/>
20
+ <path d="M16 14.2 26.5 19.3 16 22.4 5.5 19.3Z" fill="#ffffff"/>
21
+ <path d="M16 20 25.4 24.6 16 27 6.6 24.6Z" fill="#ffffff"/>
3
22
  </svg>
@@ -1,3 +1,22 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
2
- <image width="32" height="32" xlink:href="data:image/png;base64,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"/>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#684e2c"/>
5
+ <stop offset="100%" stop-color="#235c52"/>
6
+ </linearGradient>
7
+ <radialGradient id="shine" cx="24%" cy="15%" r="70%">
8
+ <stop offset="0%" stop-color="#ffffff" stop-opacity="0.20"/>
9
+ <stop offset="100%" stop-color="#ffffff" stop-opacity="0"/>
10
+ </radialGradient>
11
+ </defs>
12
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#000000" stroke-opacity="0.24" stroke-width="1"/>
13
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#shine)"/>
14
+ <path d="M2.5 17h27v3.5c0 5-4 9-9 9h-9c-5 0-9-4-9-9Z" fill="#000000" opacity="0.12"/>
15
+ <rect x="3" y="3" width="26" height="26" rx="8.5" ry="8.5" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="1"/>
16
+ <path d="M16 6.25 26.15 12.3 16 16.3 5.85 12.3Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
17
+ <path d="M16 14.75 25.85 19.45 16 22.25 6.15 19.45Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
18
+ <path d="M16 20.45 24.85 24.75 16 26.85 7.15 24.75Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
19
+ <path d="M16 5.7 26.8 12.1 16 16.5 5.2 12.1Z" fill="#fff9ed"/>
20
+ <path d="M16 14.2 26.5 19.3 16 22.4 5.5 19.3Z" fill="#fff9ed"/>
21
+ <path d="M16 20 25.4 24.6 16 27 6.6 24.6Z" fill="#fff9ed"/>
3
22
  </svg>
Binary file
Binary file
@@ -28,10 +28,16 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
28
28
  Win32Window::Point origin(10, 10);
29
29
  Win32Window::Size size(1280, 720);
30
30
  if (!window.Create(L"NeoAgent", origin, size)) {
31
+ ::MessageBoxW(nullptr,
32
+ L"NeoAgent failed to start. The Flutter engine could not be "
33
+ L"initialized. Ensure the application was installed correctly "
34
+ L"and all required files are present.",
35
+ L"NeoAgent — Startup Error",
36
+ MB_OK | MB_ICONERROR);
31
37
  ::CoUninitialize();
32
38
  return EXIT_FAILURE;
33
39
  }
34
- window.SetQuitOnClose(false);
40
+ window.SetQuitOnClose(true);
35
41
 
36
42
  ::MSG msg;
37
43
  while (true) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.4.1-beta.21",
3
+ "version": "2.4.1-beta.23",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "AGPL-3.0-only",
6
6
  "main": "server/index.js",
@@ -1 +1 @@
1
- 85aec387d5291e4a8061af58ef035c07
1
+ 2285030b457380c855d32a3568048ed7
Binary file
@@ -1,3 +1,22 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
2
- <image width="32" height="32" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAHiElEQVR4nG1XW48c1RH+6pzTc9mZ2Zlde23HAa1ZY4MiKyFISV6Sh+QJpLzwgsQT4o+AxM/ghUck/gC8RYpAQpEMwbEcO4aNoxjHXts7M3uZS/c5p6Kq093Ts9BST/f05VTVV199VU1Y3wyAKCe/uPrCywh4p2C8ESK/yqBRYBhmIMoOQM51JwLkWC7CrLcnINwF+HMK+OTp04ffnbUhGzWMWwDhV7u7o5zC+xH8XmQzCpHhIyOUhplZDanh+ijLcH2sliU5im/ME2b6OOb2w+n0P5PKVtMBvXBt9/JrhsynAF1b+ogQWewTAyTH5MDKCXm9OkvnFQTqjvonOxFZIgPmeD8Cb0+fPvp7ZZMqSK6/9PNfcsRfItN27kPBTE4MS+QpyrSkOFHaWIO9vrZKQ3JLEdBb3hiTgfmQDf1xcvDDLbGtDuzt7Q3IL7+OTHs+REHcBXmrhLfpQDK8ijpBvE4k+Rubz6zueEPWAbxPofP6eLx/rNHHfPEBw+xJ5EGNy6IJUoW7diZl2RBpZE3j6mBpWJ4nfSYZL1kjvy5yKEC0x2b+gTxOu7sXr8C724G5G2LK9SrH6/ArXiDEEvs6yWWaqmCbXKidkAfKU0q0mpMLNxwX9l0m9HzkwEymyfKyunTrtAysNY28lqgoLxghAnlg+JBQWnFB0Ki5oKXB4GiM6VGw77rIeDNE5hgV0DXjQobMEc5vtiFVscgj8iLCx/VKEGSsJXRbRp2ZLWNao4FQCUR1LhDIrTdNYH4lMpelxspyeTj3ES9e6uPPv38RJ8uAwyOPk3lAHko9IAOQBcggMGFRMI4XEUUA+h0La6hBxDPlAk0zMdErjkHDkjjihD4scLbbFuc3DW5/P8bkJMCZklREMM7CWAMyJvFDhEp0wwdFSpjcbVvwEghCLEqE1vcTckRKKjN0kqImidJ1ws+2O9h/OMPzY48sE2glYAvXdiBD4NiQYUMwLQNyFiEvEH3EbBnQzixiTPWhqriGQWK0q5lcXhfpu7Ddwfgox3wZ4NzKeNbJFNbIBLvRhmtnurRfeoTZQiXetFtgFIhFoWkUtELhU3DrLqgTrikiITB6XafHo5lHt22wzFmhti2nDDetDL2dPgabFp0sIsDg1HdxPN3A4mAKLgqYzIFDRIwBxgpPaK1EExppd5XQVDc7mcHRrNB2pXlG0Oj1CWPQvTDAzjnCS90Cl7uycMSDmce/sh6eYwv5/56JtGk6OA/KDwmgLoGGWooLqxSo0Ijsspaa1ncEWi2LvJRjt7mB3laGq/0F/nSlg+svtFUxbz9cYv4gx3HoozjuIU6PpC61QmQ9QUEDlQUrCS0J7c7ywvuYGg4BszxiOGijWKbaNBsdtFoGuyOHG1f7uPKbP4CDB3/1JW4eznGvcKD+BvjoOIUlAiGLiYAJD2pDq6M52820xsv/PkQsi4hBv6WlKVGFVhvROU2HRCg7CVEzi5BlajTJb2IdZS4hUUdfBdtAgKuGwqkKxHFROynHk9Mc2/0NDLbaOJ3nOLU7+M4D/3y8BH3zhXbzW88i/h178FkXcXmgCzMnHtgsQ/Q+OVxJIp1NAa2cEKVTxMThUhMm41NsXT6PQa+HkxOPO8ML8OMZbhUBngl3Ftt42Bkg/+EJ+HSWCGYIttOBP5mDWhlQFM1kl0VAZRk2hgfVf0uwhlVE9NkYMX4yRv+iQX97hNMiwzfhEu4sCExWnV4+eoz438eIhYdtZ2i3MsyeTTQarYJYtdNV9ExQBNThasJRFDyj5QxyLgkZI0wIOH7yDIvZAv3FZfD2ECci27MFwvgI8flEa797bog2EY4eHagz2WgTYb5YF8CSI9KTaHT+0pgZI5WDcs4QtROSiAp6bT6plo1zYJFhY9Aa9GC7HYQYEfNcJ8zrv74CziPu/vUfoBBUFY2kYTythgnIbCidgKR9Ojuh4blLX4Hot1HxFimoulh6wTppOLKXPGk0IXFXFLIl5dltQRrEycFEpVnWMYM+4skMLCSUHlyKGQxF45xE+DdHhM8Y+F1Zgal06mmXVBfICAKpA1b5E3EhHVAYxfEM82dTbUJCPjW+0UWcL9R4rYTlu0TEOt0QfUbD4cUr0dJtAN3EBZmik/JVZVNrRaN8aidL3ZBqSS3XgKQheQ/Oi8pg413hrWU4NzdtumGm0ycPmPkjMsYw2Ndj1KplNhpp/WGgdV6N/tWIpsalByxzcJ5qv2lcB1VD3rTahqz9aHrv3gMdcre2tgYFtb8mwh5H9tKk6lptfgfU3pQuVWxWVSwnTlG8WukqvRXe6B9PWebYmH2H3uvj/Zs6lmM8Hk85xreYcUhknDb0akD80XbGuB5T51o3LrupjAs8hRq39jA699Z4/+a0ia5+Jm0Md14z1n5KRNfKFi3VVTdvvVLp/FpTSZxQ7jSJJrRIhLMma4nw3PeEt2f376x9mqHpxHA4HAWz8T4Mv0cwo7NA6HBVQVs1lzK/YlyjF7glcq0UK9cnIPqYNtyH02+//cmP02qrP503d3ZeBtt3ItMbIHqVQCOZwJtSWun52q6Qm8iGJmTMXYA+B+OTo+/v/OTn+f8B0flnBgWZoEkAAAAASUVORK5CYII="/>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#9e8052"/>
5
+ <stop offset="100%" stop-color="#439081"/>
6
+ </linearGradient>
7
+ <radialGradient id="shine" cx="24%" cy="15%" r="70%">
8
+ <stop offset="0%" stop-color="#fff4d8" stop-opacity="0.24"/>
9
+ <stop offset="100%" stop-color="#fff4d8" stop-opacity="0"/>
10
+ </radialGradient>
11
+ </defs>
12
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1"/>
13
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#shine)"/>
14
+ <path d="M2.5 17h27v3.5c0 5-4 9-9 9h-9c-5 0-9-4-9-9Z" fill="#000000" opacity="0.08"/>
15
+ <rect x="3" y="3" width="26" height="26" rx="8.5" ry="8.5" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="1"/>
16
+ <path d="M16 6.25 26.15 12.3 16 16.3 5.85 12.3Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
17
+ <path d="M16 14.75 25.85 19.45 16 22.25 6.15 19.45Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
18
+ <path d="M16 20.45 24.85 24.75 16 26.85 7.15 24.75Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
19
+ <path d="M16 5.7 26.8 12.1 16 16.5 5.2 12.1Z" fill="#ffffff"/>
20
+ <path d="M16 14.2 26.5 19.3 16 22.4 5.5 19.3Z" fill="#ffffff"/>
21
+ <path d="M16 20 25.4 24.6 16 27 6.6 24.6Z" fill="#ffffff"/>
3
22
  </svg>
@@ -1,3 +1,22 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
2
- <image width="32" height="32" xlink:href="data:image/png;base64,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"/>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#684e2c"/>
5
+ <stop offset="100%" stop-color="#235c52"/>
6
+ </linearGradient>
7
+ <radialGradient id="shine" cx="24%" cy="15%" r="70%">
8
+ <stop offset="0%" stop-color="#ffffff" stop-opacity="0.20"/>
9
+ <stop offset="100%" stop-color="#ffffff" stop-opacity="0"/>
10
+ </radialGradient>
11
+ </defs>
12
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#000000" stroke-opacity="0.24" stroke-width="1"/>
13
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#shine)"/>
14
+ <path d="M2.5 17h27v3.5c0 5-4 9-9 9h-9c-5 0-9-4-9-9Z" fill="#000000" opacity="0.12"/>
15
+ <rect x="3" y="3" width="26" height="26" rx="8.5" ry="8.5" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="1"/>
16
+ <path d="M16 6.25 26.15 12.3 16 16.3 5.85 12.3Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
17
+ <path d="M16 14.75 25.85 19.45 16 22.25 6.15 19.45Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
18
+ <path d="M16 20.45 24.85 24.75 16 26.85 7.15 24.75Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
19
+ <path d="M16 5.7 26.8 12.1 16 16.5 5.2 12.1Z" fill="#fff9ed"/>
20
+ <path d="M16 14.2 26.5 19.3 16 22.4 5.5 19.3Z" fill="#fff9ed"/>
21
+ <path d="M16 20 25.4 24.6 16 27 6.6 24.6Z" fill="#fff9ed"/>
3
22
  </svg>
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"4c525dac5ebe5971c5708ef73558ed8edcf4a3
37
37
 
38
38
  _flutter.loader.load({
39
39
  serviceWorkerSettings: {
40
- serviceWorkerVersion: "3261890854" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
40
+ serviceWorkerVersion: "4078228684" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
41
41
  }
42
42
  });
Binary file
Binary file
@@ -132757,7 +132757,7 @@ r===$&&A.b()
132757
132757
  o.push(A.jJ(p,A.j7(!1,new A.a3(B.uk,A.e1(new A.cJ(B.ho,new A.a7e(r,p),p),p,p),p),!1,B.H,!0),p,p,0,0,0,p))}r=!1
132758
132758
  if(!s.ay)if(!s.ch){r=s.e
132759
132759
  r===$&&A.b()
132760
- r=B.b.t("mpmhsxvz-d1ec7f5").length!==0&&r.b}if(r){r=s.d
132760
+ r=B.b.t("mppvjj3c-da55ad8").length!==0&&r.b}if(r){r=s.d
132761
132761
  r===$&&A.b()
132762
132762
  r=r.ad&&!r.Z?84:0
132763
132763
  q=s.e
@@ -138212,7 +138212,7 @@ $S:0}
138212
138212
  A.ZH.prototype={}
138213
138213
  A.Sw.prototype={
138214
138214
  nc(a){var s=this
138215
- if(B.b.t("mpmhsxvz-d1ec7f5").length===0||s.a!=null)return
138215
+ if(B.b.t("mppvjj3c-da55ad8").length===0||s.a!=null)return
138216
138216
  s.AH()
138217
138217
  s.a=A.qf(B.R3,new A.b9B(s))},
138218
138218
  AH(){var s=0,r=A.l(t.H),q,p=2,o=[],n=this,m,l,k,j,i,h,g,f
@@ -138230,7 +138230,7 @@ if(!t.f.b(k)){s=1
138230
138230
  break}i=J.U(k,"buildId")
138231
138231
  h=i==null?null:B.b.t(J.p(i))
138232
138232
  j=h==null?"":h
138233
- if(J.bj(j)===0||J.d(j,"mpmhsxvz-d1ec7f5")){s=1
138233
+ if(J.bj(j)===0||J.d(j,"mppvjj3c-da55ad8")){s=1
138234
138234
  break}n.b=!0
138235
138235
  n.F()
138236
138236
  p=2
@@ -138247,7 +138247,7 @@ case 2:return A.i(o.at(-1),r)}})
138247
138247
  return A.k($async$AH,r)},
138248
138248
  vs(){var s=0,r=A.l(t.H),q,p=2,o=[],n=this,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1
138249
138249
  var $async$vs=A.h(function(a2,a3){if(a2===1){o.push(a3)
138250
- s=p}for(;;)switch(s){case 0:if(B.b.t("mpmhsxvz-d1ec7f5").length===0||n.c){s=1
138250
+ s=p}for(;;)switch(s){case 0:if(B.b.t("mppvjj3c-da55ad8").length===0||n.c){s=1
138251
138251
  break}n.c=!0
138252
138252
  n.F()
138253
138253
  p=4