Add web push notifications for new inbox items

This commit is contained in:
Ian Gulliver
2026-10-14 21:25:01 -07:00
parent 01c60d6618
commit 8e4c40eb5f
40 changed files with 1724 additions and 202 deletions
+224 -76
View File
@@ -439,6 +439,24 @@ type MessageCreate struct {
Text string `json:"text"`
}
// NotificationPrefs Which new inbox items send this user a push notification.
type NotificationPrefs struct {
// BlockingQuestions Questions asked with blocking: true. On by default.
BlockingQuestions bool `json:"blocking_questions"`
// Errors session_error items.
Errors bool `json:"errors"`
// Questions Non-blocking questions.
Questions bool `json:"questions"`
// RateLimits rate_limited items.
RateLimits bool `json:"rate_limits"`
// Reports Turn summaries.
Reports bool `json:"reports"`
}
// Project defines model for Project.
type Project struct {
CreatedAt time.Time `json:"created_at"`
@@ -456,6 +474,22 @@ type ProjectCreate struct {
RepoPath string `json:"repo_path"`
}
// PushKey defines model for PushKey.
type PushKey struct {
// PublicKey Base64url
PublicKey string `json:"public_key"`
}
// PushSubscription defines model for PushSubscription.
type PushSubscription struct {
// Auth The subscription's auth secret
Auth string `json:"auth"`
Endpoint string `json:"endpoint"`
// P256dh The subscription's p256dh key
P256dh string `json:"p256dh"`
}
// SessionCreate defines model for SessionCreate.
type SessionCreate struct {
// Images Blob ids from uploadBlob, sent to the agent as images alongside the prompt.
@@ -554,6 +588,9 @@ type User struct {
GitEmail string `json:"git_email"`
GitName string `json:"git_name"`
Login string `json:"login"`
// NotificationPrefs Which new inbox items send this user a push notification.
NotificationPrefs NotificationPrefs `json:"notification_prefs"`
}
// UserUpdate defines model for UserUpdate.
@@ -576,6 +613,11 @@ type ListInboxParams struct {
IncludeSnoozed *bool `form:"include_snoozed,omitempty" json:"include_snoozed,omitempty"`
}
// RemovePushSubscriptionParams defines parameters for RemovePushSubscription.
type RemovePushSubscriptionParams struct {
Endpoint string `form:"endpoint" json:"endpoint"`
}
// GetTaskChangesParams defines parameters for GetTaskChanges.
type GetTaskChangesParams struct {
// Since A commit to compare with instead of the merge-base, such as a user.message event's head.
@@ -602,6 +644,12 @@ type RespondInboxJSONRequestBody = InboxRespond
// UpdateMeJSONRequestBody defines body for UpdateMe for application/json ContentType.
type UpdateMeJSONRequestBody = UserUpdate
// UpdateNotificationPrefsJSONRequestBody defines body for UpdateNotificationPrefs for application/json ContentType.
type UpdateNotificationPrefsJSONRequestBody = NotificationPrefs
// AddPushSubscriptionJSONRequestBody defines body for AddPushSubscription for application/json ContentType.
type AddPushSubscriptionJSONRequestBody = PushSubscription
// CreateProjectJSONRequestBody defines body for CreateProject for application/json ContentType.
type CreateProjectJSONRequestBody = ProjectCreate
@@ -644,6 +692,15 @@ type ServerInterface interface {
// (PUT /api/me)
UpdateMe(w http.ResponseWriter, r *http.Request)
// (PUT /api/me/notifications)
UpdateNotificationPrefs(w http.ResponseWriter, r *http.Request)
// (DELETE /api/me/push-subscriptions)
RemovePushSubscription(w http.ResponseWriter, r *http.Request, params RemovePushSubscriptionParams)
// (POST /api/me/push-subscriptions)
AddPushSubscription(w http.ResponseWriter, r *http.Request)
// (GET /api/projects)
ListProjects(w http.ResponseWriter, r *http.Request)
@@ -659,6 +716,9 @@ type ServerInterface interface {
// (POST /api/projects/{projectId}/tasks)
CreateTask(w http.ResponseWriter, r *http.Request, projectId string)
// (GET /api/push/key)
GetPushKey(w http.ResponseWriter, r *http.Request)
// (GET /api/sessions/{sessionId})
GetSession(w http.ResponseWriter, r *http.Request, sessionId string)
@@ -959,6 +1019,67 @@ func (siw *ServerInterfaceWrapper) UpdateMe(w http.ResponseWriter, r *http.Reque
handler.ServeHTTP(w, r)
}
// UpdateNotificationPrefs operation middleware
func (siw *ServerInterfaceWrapper) UpdateNotificationPrefs(w http.ResponseWriter, r *http.Request) {
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.UpdateNotificationPrefs(w, r)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// RemovePushSubscription operation middleware
func (siw *ServerInterfaceWrapper) RemovePushSubscription(w http.ResponseWriter, r *http.Request) {
var err error
_ = err
// Parameter object where we will unmarshal all parameters from the context
var params RemovePushSubscriptionParams
// ------------- Required query parameter "endpoint" -------------
err = runtime.BindQueryParameterWithOptions("form", true, true, "endpoint", r.URL.Query(), &params.Endpoint, runtime.BindQueryParameterOptions{Type: "string", Format: ""})
if err != nil {
var requiredError *runtime.RequiredParameterError
if errors.As(err, &requiredError) {
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "endpoint"})
} else {
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "endpoint", Err: err})
}
return
}
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.RemovePushSubscription(w, r, params)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// AddPushSubscription operation middleware
func (siw *ServerInterfaceWrapper) AddPushSubscription(w http.ResponseWriter, r *http.Request) {
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.AddPushSubscription(w, r)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// ListProjects operation middleware
func (siw *ServerInterfaceWrapper) ListProjects(w http.ResponseWriter, r *http.Request) {
@@ -1065,6 +1186,20 @@ func (siw *ServerInterfaceWrapper) CreateTask(w http.ResponseWriter, r *http.Req
handler.ServeHTTP(w, r)
}
// GetPushKey operation middleware
func (siw *ServerInterfaceWrapper) GetPushKey(w http.ResponseWriter, r *http.Request) {
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.GetPushKey(w, r)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// GetSession operation middleware
func (siw *ServerInterfaceWrapper) GetSession(w http.ResponseWriter, r *http.Request) {
@@ -1651,6 +1786,10 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/me", wrapper.GetMe)
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me", wrapper.UpdateMe)
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me/notifications", wrapper.UpdateNotificationPrefs)
m.HandleFunc(http.MethodDelete+" "+options.BaseURL+"/api/me/push-subscriptions", wrapper.RemovePushSubscription)
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/me/push-subscriptions", wrapper.AddPushSubscription)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/push/key", wrapper.GetPushKey)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects", wrapper.ListProjects)
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/projects", wrapper.CreateProject)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects/{projectId}", wrapper.GetProject)
@@ -1686,82 +1825,91 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
// const string: with thousands of chunks the chained `+` fold is several
// times slower for the Go compiler than parsing a slice literal.
var swaggerSpec = []string{
"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",
"/w==",
}
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,