@gotcos/glasses-server 6.16.5 → 6.17.0

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.
@@ -127,6 +127,19 @@ async function reverseGeocode(lat: number, lon: number): Promise<string> {
127
127
  }
128
128
  }
129
129
 
130
+ /** Ensure a city label before any weather JSON leaves the server (3s capped). */
131
+ async function ensureCityLabel(lat: number, lon: number, source: 'query' | 'last' | 'env'): Promise<void> {
132
+ if (lastKnownCity) return
133
+ if (source === 'env') {
134
+ const env = envDefaultCoords()
135
+ if (env?.city) {
136
+ lastKnownCity = env.city
137
+ return
138
+ }
139
+ }
140
+ await reverseGeocode(lat, lon)
141
+ }
142
+
130
143
  export async function fetchWeather(
131
144
  queryLat?: number,
132
145
  queryLon?: number,
@@ -147,19 +160,21 @@ export async function fetchWeather(
147
160
  lastKnownLat = useLat
148
161
  lastKnownLon = useLon
149
162
  weatherFetchedAt = 0
150
- // Blocker fix: wait for city before first paint (capped).
151
- await reverseGeocode(useLat, useLon)
152
- } else if (source === 'env' && !lastKnownCity) {
153
- const env = envDefaultCoords()
154
- if (env?.city) lastKnownCity = env.city
155
- lastKnownLat = useLat
156
- lastKnownLon = useLon
157
- } else if (lastKnownLat == null) {
163
+ lastKnownCity = '' // force fresh reverse-geocode for the new place
164
+ } else if (lastKnownLat == null || lastKnownLon == null) {
158
165
  lastKnownLat = useLat
159
166
  lastKnownLon = useLon
160
167
  }
161
168
 
169
+ // Warning fix: never return weather (cached or fresh) without a city when
170
+ // we can still resolve one — closes reverse-geocode race on first paint.
171
+ await ensureCityLabel(useLat, useLon, source)
172
+
162
173
  if (cachedWeather && Date.now() - weatherFetchedAt < WEATHER_TTL_MS) {
174
+ // Refresh location string if geocode caught up after an older cache write.
175
+ if (lastKnownCity && cachedWeather.location !== lastKnownCity) {
176
+ cachedWeather = { ...cachedWeather, location: lastKnownCity }
177
+ }
163
178
  return cachedWeather
164
179
  }
165
180
 
@@ -177,13 +192,7 @@ export async function fetchWeather(
177
192
  const code = data.current?.weather_code
178
193
  if (typeof temp !== 'number' || typeof code !== 'number') return cachedWeather
179
194
 
180
- if (!lastKnownCity && source === 'env') {
181
- const env = envDefaultCoords()
182
- if (env?.city) lastKnownCity = env.city
183
- }
184
- if (!lastKnownCity) {
185
- await reverseGeocode(useLat, useLon)
186
- }
195
+ await ensureCityLabel(useLat, useLon, source)
187
196
 
188
197
  cachedWeather = {
189
198
  temp: `${Math.round(temp)}\u00B0F`,
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env tsx
2
+ // Creates a fresh short-number namespace without touching sessions or archives.
3
+ // Restart the server afterward so every new exchange is stamped into the era.
4
+ //
5
+ // npx tsx server/scripts/reset-message-era.ts --confirm
6
+
7
+ import { createMessageEra, currentMessageEraState } from '../lib/message-era.js'
8
+
9
+ if (!process.argv.includes('--confirm')) {
10
+ const current = currentMessageEraState()
11
+ console.error(`Current message era: ${current.era}`)
12
+ console.error('Refusing to reset without --confirm. History will be retained.')
13
+ process.exit(2)
14
+ }
15
+
16
+ const next = createMessageEra()
17
+ console.log(JSON.stringify({
18
+ status: 'created',
19
+ ...next,
20
+ history: 'retained',
21
+ restartRequired: true,
22
+ verify: 'GET /api/message-counter should return { max: 0 or small, era: "<era above>" } after server restart',
23
+ nextSteps: [
24
+ 'Restart LaunchAgent / Control Update Server generation',
25
+ 'Phone reconnect so syncMessageEra clears the live list',
26
+ 'Send a test message — expect #1 (or low single digits)',
27
+ ],
28
+ }, null, 2))