feat(agent): add opt-in push notifications

This commit is contained in:
2026-10-14 22:03:21 -07:00
parent 80748f764f
commit a1c0264d36
51 changed files with 4815 additions and 121 deletions
+42 -3
View File
@@ -26,6 +26,12 @@ attachment_capability = True
next_upload_error = None
blocked_proxy = False
transcript_comparison = False
PUSH_SOURCE = '11111111-1111-4111-8111-111111111111'
push_installations = {}
push_retired = set()
push_requests = []
push_available = True
auth_required = False
CAPABILITY = dict(version=1, maxCount=8, maxTotalBytes=33554432, maxImageBytes=6291456,
maxFileBytes=8388608, imageMimeTypes=['image/png', 'image/jpeg', 'image/gif', 'image/webp'],
maxImagePixels=50000000, maxImageDimension=16384, quotaBytes=1073741824, usedBytes=0,
@@ -88,7 +94,7 @@ async def reply(content):
await broadcast(dict(type='activity', conversationId='fixture-root', activity=activity()))
async def route(request):
global read_cursor, cursor, busy, attachment_capability, next_upload_error, blocked_proxy, transcript_comparison
global read_cursor, cursor, busy, attachment_capability, next_upload_error, blocked_proxy, transcript_comparison, push_available, auth_required
path = request.path
log.append(dict(method=request.method, path=path, query=dict(request.query)))
if path == '/control':
@@ -100,6 +106,8 @@ async def route(request):
reply_tasks.clear()
messages.clear(); requests.clear(); attempts.clear(); cursor = 0; read_cursor = 0; busy = False
attachment_capability = True; next_upload_error = None; blocked_proxy = False; transcript_comparison = False
push_installations.clear(); push_retired.clear(); push_requests.clear(); log.clear()
push_available = True; auth_required = False
for i in range(body.get('count', 3)):
message(f'History message {i + 1}: local simulator fixture.')
elif action == 'transcript-comparison':
@@ -126,13 +134,21 @@ async def route(request):
await broadcast(dict(type='activity', conversationId='fixture-root', activity=activity()))
elif action == 'read':
read_cursor = cursor
await broadcast(dict(type='read_state', sourceId=PUSH_SOURCE, cursor=str(read_cursor), updatedAt=stamp()))
elif action == 'push-available':
push_available = body.get('enabled', True)
elif action == 'auth-required':
auth_required = body.get('enabled', True)
elif action == 'disconnect':
for socket in list(sockets):
await socket.close(code=1012)
elif action == 'malformed':
await broadcast(dict(type='messages', conversationId='fixture-root', messages=[{'id': 'broken'}], cursor='999999', beforeCursor=None, hasMore=False))
return web.json_response(dict(cursor=cursor, readCursor=read_cursor, messages=messages, requests=requests, log=log))
return web.json_response(dict(cursor=cursor, readCursor=read_cursor, messages=messages, requests=requests, log=log,
pushRequests=push_requests, pushActive=len(push_installations), pushRetired=len(push_retired)))
if path == '/api/v1/auth/session':
if auth_required and request.headers.get('Authorization') != 'Bearer fixture-token':
return web.json_response(dict(message='Fixture authentication required'), status=401)
return web.json_response(dict(authenticated=True, mode='token'))
comparison = dict(id='fade-comparison', title='Transcript fade comparison', createdAt=stamp(), updatedAt=stamp())
if path == '/api/v1/workspace-items':
@@ -157,6 +173,29 @@ async def route(request):
if attachment_capability:
descriptor['capabilities'] = {'attachments': CAPABILITY}
return web.json_response(descriptor)
if path == '/api/v1/agent/push/config':
if not push_available:
return web.json_response(dict(message='Old server fixture'), status=404)
return web.json_response(dict(version=1, enabled=True, apnsAvailable=True, webPushAvailable=False,
sourceId=PUSH_SOURCE, quarantined=False, policy={}))
if path.startswith('/api/v1/agent/push/installations/'):
installation = str(uuid.UUID(path.rsplit('/', 1)[1]))
if request.method == 'DELETE':
push_installations.pop(installation, None); push_retired.add(installation)
push_requests.append(dict(method='DELETE', installationId=installation))
return web.Response(status=204)
if request.method == 'PUT':
body = await request.json()
assert set(body) == {'transport', 'enabled', 'token', 'environment', 'topic'}
assert body['transport'] == 'apns' and body['enabled'] is True
assert body['environment'] == 'sandbox' and body['topic'] == 'net.buzzert.sybil2'
assert body['token'] == '00010aff' + '42' * 28 # explicitly injected synthetic token
if installation in push_retired:
return web.json_response(dict(message='Retired installation'), status=409)
version = push_installations.get(installation, 0) + 1
push_installations[installation] = version
push_requests.append(dict(method='PUT', installationId=installation, environment='sandbox'))
return web.json_response(dict(installationId=installation, transport='apns', enabled=True, version=version))
if path == '/api/v1/agent/attachments' and request.method == 'POST':
if not attachment_capability:
return attachment_error(503, 'attachments_unavailable', 'Attachments are unavailable.')
@@ -217,7 +256,7 @@ async def route(request):
if path == '/api/v1/agent/read-state':
if request.method == 'PUT':
read_cursor = max(read_cursor, int((await request.json())['cursor']))
return web.json_response(dict(cursor=str(read_cursor), updatedAt=stamp()))
return web.json_response(dict(cursor=str(read_cursor), updatedAt=stamp(), sourceId=PUSH_SOURCE))
if path == '/api/v1/agent/messages':
if request.method == 'POST':
body = await request.json()