@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.
- package/.env.example +4 -1
- package/CHANGELOG.md +71 -0
- package/README.md +57 -0
- package/package.json +2 -2
- package/server/lib/archive.ts +9 -3
- package/server/lib/claude-bridge.ts +2 -0
- package/server/lib/codex-bridge.ts +2 -0
- package/server/lib/conversation.ts +38 -0
- package/server/lib/cursor-bridge.ts +6 -3
- package/server/lib/message-era.ts +94 -0
- package/server/lib/profile.ts +24 -2
- package/server/lib/prompt-draft-store.ts +39 -3
- package/server/lib/query-job-runtime.ts +36 -6
- package/server/lib/speaker-embeddings.ts +169 -6
- package/server/routes/health.ts +7 -0
- package/server/routes/message-ref.ts +44 -10
- package/server/routes/prompt-drafts.ts +48 -21
- package/server/routes/query.ts +20 -1
- package/server/routes/sessions.ts +23 -6
- package/server/routes/voice.ts +9 -3
- package/server/routes/welcome-context.ts +24 -15
- package/server/scripts/reset-message-era.ts +28 -0
|
@@ -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
|
-
//
|
|
151
|
-
|
|
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
|
-
|
|
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))
|