feat: agent browser (#200)

* feat: agent browser

* chore: complete docker and action config

* feat: more actions

* feat: browser tab switch

* fix: browser build

* fix: lint

* fix: migrations
This commit is contained in:
Acbox Liu
2026-03-07 15:06:00 +08:00
committed by GitHub
parent 21999b49f4
commit bafd327b6b
67 changed files with 3586 additions and 47 deletions
+120
View File
@@ -0,0 +1,120 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: browser_contexts.sql
package sqlc
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createBrowserContext = `-- name: CreateBrowserContext :one
INSERT INTO browser_contexts (name, config)
VALUES ($1, $2)
RETURNING id, name, config, created_at, updated_at
`
type CreateBrowserContextParams struct {
Name string `json:"name"`
Config []byte `json:"config"`
}
func (q *Queries) CreateBrowserContext(ctx context.Context, arg CreateBrowserContextParams) (BrowserContext, error) {
row := q.db.QueryRow(ctx, createBrowserContext, arg.Name, arg.Config)
var i BrowserContext
err := row.Scan(
&i.ID,
&i.Name,
&i.Config,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const deleteBrowserContext = `-- name: DeleteBrowserContext :exec
DELETE FROM browser_contexts WHERE id = $1
`
func (q *Queries) DeleteBrowserContext(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteBrowserContext, id)
return err
}
const getBrowserContextByID = `-- name: GetBrowserContextByID :one
SELECT id, name, config, created_at, updated_at FROM browser_contexts WHERE id = $1
`
func (q *Queries) GetBrowserContextByID(ctx context.Context, id pgtype.UUID) (BrowserContext, error) {
row := q.db.QueryRow(ctx, getBrowserContextByID, id)
var i BrowserContext
err := row.Scan(
&i.ID,
&i.Name,
&i.Config,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const listBrowserContexts = `-- name: ListBrowserContexts :many
SELECT id, name, config, created_at, updated_at FROM browser_contexts ORDER BY created_at DESC
`
func (q *Queries) ListBrowserContexts(ctx context.Context) ([]BrowserContext, error) {
rows, err := q.db.Query(ctx, listBrowserContexts)
if err != nil {
return nil, err
}
defer rows.Close()
var items []BrowserContext
for rows.Next() {
var i BrowserContext
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Config,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateBrowserContext = `-- name: UpdateBrowserContext :one
UPDATE browser_contexts
SET name = $1,
config = $2,
updated_at = now()
WHERE id = $3
RETURNING id, name, config, created_at, updated_at
`
type UpdateBrowserContextParams struct {
Name string `json:"name"`
Config []byte `json:"config"`
ID pgtype.UUID `json:"id"`
}
func (q *Queries) UpdateBrowserContext(ctx context.Context, arg UpdateBrowserContextParams) (BrowserContext, error) {
row := q.db.QueryRow(ctx, updateBrowserContext, arg.Name, arg.Config, arg.ID)
var i BrowserContext
err := row.Scan(
&i.ID,
&i.Name,
&i.Config,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
+1 -1
View File
@@ -590,7 +590,7 @@ WITH updated AS (
SET display_name = $1,
updated_at = now()
WHERE bots.id = $2
RETURNING id, owner_user_id, type, display_name, avatar_url, is_active, status, max_context_load_time, max_context_tokens, language, allow_guest, reasoning_enabled, reasoning_effort, max_inbox_items, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, heartbeat_model_id, metadata, created_at, updated_at
RETURNING id, owner_user_id, type, display_name, avatar_url, is_active, status, max_context_load_time, max_context_tokens, language, allow_guest, reasoning_enabled, reasoning_effort, max_inbox_items, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, heartbeat_model_id, browser_context_id, metadata, created_at, updated_at
)
SELECT
updated.id AS id,
+9
View File
@@ -30,6 +30,7 @@ type Bot struct {
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
HeartbeatModelID pgtype.UUID `json:"heartbeat_model_id"`
BrowserContextID pgtype.UUID `json:"browser_context_id"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
@@ -153,6 +154,14 @@ type BotStorageBinding struct {
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type BrowserContext struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Config []byte `json:"config"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type ChannelIdentity struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
+16 -4
View File
@@ -27,6 +27,7 @@ SET max_context_load_time = 1440,
heartbeat_model_id = NULL,
search_provider_id = NULL,
memory_provider_id = NULL,
browser_context_id = NULL,
updated_at = now()
WHERE id = $1
`
@@ -52,12 +53,14 @@ SELECT
chat_models.id AS chat_model_id,
heartbeat_models.id AS heartbeat_model_id,
search_providers.id AS search_provider_id,
memory_providers.id AS memory_provider_id
memory_providers.id AS memory_provider_id,
browser_contexts.id AS browser_context_id
FROM bots
LEFT JOIN models AS chat_models ON chat_models.id = bots.chat_model_id
LEFT JOIN models AS heartbeat_models ON heartbeat_models.id = bots.heartbeat_model_id
LEFT JOIN search_providers ON search_providers.id = bots.search_provider_id
LEFT JOIN memory_providers ON memory_providers.id = bots.memory_provider_id
LEFT JOIN browser_contexts ON browser_contexts.id = bots.browser_context_id
WHERE bots.id = $1
`
@@ -77,6 +80,7 @@ type GetSettingsByBotIDRow struct {
HeartbeatModelID pgtype.UUID `json:"heartbeat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
BrowserContextID pgtype.UUID `json:"browser_context_id"`
}
func (q *Queries) GetSettingsByBotID(ctx context.Context, id pgtype.UUID) (GetSettingsByBotIDRow, error) {
@@ -98,6 +102,7 @@ func (q *Queries) GetSettingsByBotID(ctx context.Context, id pgtype.UUID) (GetSe
&i.HeartbeatModelID,
&i.SearchProviderID,
&i.MemoryProviderID,
&i.BrowserContextID,
)
return i, err
}
@@ -119,9 +124,10 @@ WITH updated AS (
heartbeat_model_id = COALESCE($12::uuid, bots.heartbeat_model_id),
search_provider_id = COALESCE($13::uuid, bots.search_provider_id),
memory_provider_id = COALESCE($14::uuid, bots.memory_provider_id),
browser_context_id = COALESCE($15::uuid, bots.browser_context_id),
updated_at = now()
WHERE bots.id = $15
RETURNING bots.id, bots.max_context_load_time, bots.max_context_tokens, bots.max_inbox_items, bots.language, bots.allow_guest, bots.reasoning_enabled, bots.reasoning_effort, bots.heartbeat_enabled, bots.heartbeat_interval, bots.heartbeat_prompt, bots.chat_model_id, bots.heartbeat_model_id, bots.search_provider_id, bots.memory_provider_id
WHERE bots.id = $16
RETURNING bots.id, bots.max_context_load_time, bots.max_context_tokens, bots.max_inbox_items, bots.language, bots.allow_guest, bots.reasoning_enabled, bots.reasoning_effort, bots.heartbeat_enabled, bots.heartbeat_interval, bots.heartbeat_prompt, bots.chat_model_id, bots.heartbeat_model_id, bots.search_provider_id, bots.memory_provider_id, bots.browser_context_id
)
SELECT
updated.id AS bot_id,
@@ -138,12 +144,14 @@ SELECT
chat_models.id AS chat_model_id,
heartbeat_models.id AS heartbeat_model_id,
search_providers.id AS search_provider_id,
memory_providers.id AS memory_provider_id
memory_providers.id AS memory_provider_id,
browser_contexts.id AS browser_context_id
FROM updated
LEFT JOIN models AS chat_models ON chat_models.id = updated.chat_model_id
LEFT JOIN models AS heartbeat_models ON heartbeat_models.id = updated.heartbeat_model_id
LEFT JOIN search_providers ON search_providers.id = updated.search_provider_id
LEFT JOIN memory_providers ON memory_providers.id = updated.memory_provider_id
LEFT JOIN browser_contexts ON browser_contexts.id = updated.browser_context_id
`
type UpsertBotSettingsParams struct {
@@ -161,6 +169,7 @@ type UpsertBotSettingsParams struct {
HeartbeatModelID pgtype.UUID `json:"heartbeat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
BrowserContextID pgtype.UUID `json:"browser_context_id"`
ID pgtype.UUID `json:"id"`
}
@@ -180,6 +189,7 @@ type UpsertBotSettingsRow struct {
HeartbeatModelID pgtype.UUID `json:"heartbeat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
BrowserContextID pgtype.UUID `json:"browser_context_id"`
}
func (q *Queries) UpsertBotSettings(ctx context.Context, arg UpsertBotSettingsParams) (UpsertBotSettingsRow, error) {
@@ -198,6 +208,7 @@ func (q *Queries) UpsertBotSettings(ctx context.Context, arg UpsertBotSettingsPa
arg.HeartbeatModelID,
arg.SearchProviderID,
arg.MemoryProviderID,
arg.BrowserContextID,
arg.ID,
)
var i UpsertBotSettingsRow
@@ -217,6 +228,7 @@ func (q *Queries) UpsertBotSettings(ctx context.Context, arg UpsertBotSettingsPa
&i.HeartbeatModelID,
&i.SearchProviderID,
&i.MemoryProviderID,
&i.BrowserContextID,
)
return i, err
}