@gotcos/glasses-server 6.43.4 → 6.44.1
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/CHANGELOG.md +19 -0
- package/package.json +4 -2
- package/server/index.ts +2 -0
- package/server/lib/claude-bridge.ts +30 -12
- package/server/lib/maintenance-lifecycle.ts +6 -0
- package/server/lib/model-router.ts +4 -0
- package/server/lib/morning-brief-config.ts +22 -1
- package/server/lib/morning-brief-prompt.ts +16 -2
- package/server/lib/morning-brief-runtime.ts +32 -1
- package/server/lib/morning-brief-schedule.ts +19 -2
- package/server/lib/morning-brief-scheduler.ts +49 -1
- package/server/lib/python-bridge.ts +18 -4
- package/server/lib/query-job-coordinator.ts +8 -2
- package/server/lib/query-job-runtime.ts +9 -2
- package/server/lib/query-job-store.ts +5 -0
- package/server/lib/query-job-types.ts +31 -1
- package/server/lib/task-dispatcher.ts +642 -0
- package/server/lib/task-store.ts +652 -0
- package/server/routes/health.ts +8 -1
- package/server/routes/query-jobs.ts +1 -1
- package/server/routes/tasks.ts +152 -0
|
@@ -106,8 +106,12 @@ export interface QueryJobRequest {
|
|
|
106
106
|
* (see `FINGERPRINT_KEYS`), so a rollback to a build that drops it still
|
|
107
107
|
* hydrates the journal. */
|
|
108
108
|
origin?: QueryJobOrigin
|
|
109
|
+
/** Read-only dispatch constraint. Excluded from the fingerprint. */
|
|
110
|
+
dispatch?: { restricted: true; tools: readonly string[] }
|
|
109
111
|
}
|
|
110
112
|
|
|
113
|
+
export const DISPATCH_ALLOWED_TOOLS = ['Read', 'Grep', 'Glob'] as const
|
|
114
|
+
|
|
111
115
|
export interface QueryJobProviderLinkage {
|
|
112
116
|
provider?: 'claude' | 'codex' | 'cursor' | 'ollama'
|
|
113
117
|
resolvedModel?: string
|
|
@@ -214,6 +218,8 @@ export interface QueryJobStoreHealth {
|
|
|
214
218
|
/** Requests whose `origin` was present but not one this build recognises
|
|
215
219
|
* (a bare string, or an object of a later build's kind) and was dropped. */
|
|
216
220
|
originDropped: number
|
|
221
|
+
/** Public-route admissions that had `dispatch` or `origin.kind==='task'` stripped. */
|
|
222
|
+
originStripped: number
|
|
217
223
|
/** Journal `accepted` records whose stored fingerprint no longer matches the
|
|
218
224
|
* running build's `requestFingerprint` — each one is a job that did NOT
|
|
219
225
|
* hydrate. Zero is the only healthy value. */
|
|
@@ -225,6 +231,10 @@ export interface QueryJobStoreHealth {
|
|
|
225
231
|
}
|
|
226
232
|
|
|
227
233
|
const CLIENT_JOB_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
|
|
234
|
+
|
|
235
|
+
export function isClientJobId(value: string): boolean {
|
|
236
|
+
return CLIENT_JOB_ID_RE.test(value.toLowerCase())
|
|
237
|
+
}
|
|
228
238
|
const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:@/-]*$/
|
|
229
239
|
const CONTROL_RE = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g
|
|
230
240
|
const SECRET_PATTERNS: RegExp[] = [
|
|
@@ -336,6 +346,11 @@ export function parseQueryJobRequest(raw: unknown, options: ParseQueryJobRequest
|
|
|
336
346
|
// counted by the store), or a newer client would have every prompt 400'd.
|
|
337
347
|
}
|
|
338
348
|
|
|
349
|
+
const dispatch = parseDispatch(input.dispatch)
|
|
350
|
+
if (options.strictOrigin && origin?.kind === 'task' && !dispatch) {
|
|
351
|
+
throw new QueryJobValidationError('invalid_dispatch')
|
|
352
|
+
}
|
|
353
|
+
|
|
339
354
|
const attachmentIds = parseMediaIdList(input.attachmentIds)
|
|
340
355
|
const attachmentRefs = parseMediaAttachmentRefs(input.attachmentRefs ?? input.attachments)
|
|
341
356
|
if (!query.trim() && attachmentIds.length === 0 && attachmentRefs.length === 0) {
|
|
@@ -360,7 +375,22 @@ export function parseQueryJobRequest(raw: unknown, options: ParseQueryJobRequest
|
|
|
360
375
|
attachmentRefs,
|
|
361
376
|
activityToolMode,
|
|
362
377
|
...(origin ? { origin } : {}),
|
|
378
|
+
...(dispatch ? { dispatch } : {}),
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function parseDispatch(raw: unknown): QueryJobRequest['dispatch'] | undefined {
|
|
383
|
+
if (raw == null) return undefined
|
|
384
|
+
if (!raw || typeof raw !== 'object') throw new QueryJobValidationError('invalid_dispatch')
|
|
385
|
+
const rec = raw as Record<string, unknown>
|
|
386
|
+
if (rec.restricted !== true || !Array.isArray(rec.tools) || rec.tools.length === 0) {
|
|
387
|
+
throw new QueryJobValidationError('invalid_dispatch')
|
|
388
|
+
}
|
|
389
|
+
const tools = rec.tools.map(String)
|
|
390
|
+
if (tools.some(tool => !(DISPATCH_ALLOWED_TOOLS as readonly string[]).includes(tool))) {
|
|
391
|
+
throw new QueryJobValidationError('invalid_dispatch')
|
|
363
392
|
}
|
|
393
|
+
return { restricted: true, tools }
|
|
364
394
|
}
|
|
365
395
|
|
|
366
396
|
/** True when the raw admission/journal input carried an `origin` the parser
|
|
@@ -410,7 +440,7 @@ export const FINGERPRINT_KEYS = [
|
|
|
410
440
|
/** The request keys deliberately OUTSIDE the identity. Every key of
|
|
411
441
|
* `QueryJobRequest` must appear in exactly one of the two lists: adding a key
|
|
412
442
|
* without naming it here or above fails to compile, so the author picks a side. */
|
|
413
|
-
export const FINGERPRINT_EXCLUDED = ['origin'] as const satisfies readonly (keyof QueryJobRequest)[]
|
|
443
|
+
export const FINGERPRINT_EXCLUDED = ['origin', 'dispatch'] as const satisfies readonly (keyof QueryJobRequest)[]
|
|
414
444
|
type FingerprintUncovered = Exclude<keyof QueryJobRequest, typeof FINGERPRINT_KEYS[number] | typeof FINGERPRINT_EXCLUDED[number]>
|
|
415
445
|
export const FINGERPRINT_KEYS_COVER_REQUEST: FingerprintUncovered extends never ? true : never = true
|
|
416
446
|
|