[SDK] Delete the bridge agent and rework the session bundle onto lex clients (#11385)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-08-13 22:26:22 +03:00
committed by GitHub
parent 59d2bf09d7
commit 54da80dfb0
38 changed files with 812 additions and 1851 deletions
+54 -34
View File
@@ -1,12 +1,13 @@
import {
type AppBskyFeedDefs,
type AppBskyGraphDefs,
type AtpAgent,
type ComAtprotoRepoStrongRef,
} from '@atproto/api'
import {AtUri} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type AtUriString, type HandleString} from '@atproto/syntax'
import {DM_SERVICE_HEADERS, IMAGE_SIZE_CONFIG_2K_1MB} from '#/lib/constants'
import {IMAGE_SIZE_CONFIG_2K_1MB} from '#/lib/constants'
import {getLinkMeta, type LinkMeta} from '#/lib/link-meta/link-meta'
import {resolveShortLink} from '#/lib/link-meta/resolve-short-link'
import {downloadAndResize} from '#/lib/media/manip'
@@ -29,6 +30,7 @@ import {type ComposerImage} from '#/state/gallery'
import {createComposerImage} from '#/state/gallery'
import {type ChatInvitePreview} from '#/state/queries/join-links'
import {type Gif} from '#/features/gifPicker/types'
import {app, chat, com} from '#/lexicons'
import {createGIFDescription} from '../gif-alt-text'
type ResolvedExternalLink = {
@@ -94,8 +96,21 @@ export class EmbeddingDisabledError extends Error {
}
}
/**
* The clients a link resolution may need.
*
* Everything but the chat-invite branch is an appview read, and the chat invite
* preview goes through the chat client so it is proxied to the chat service.
* Both are passed together because the caller cannot know which branch a URL
* will take until it is parsed.
*/
export type LinkResolvers = {
appviewClient: Client
chatClient: Client
}
export async function resolveLink(
agent: AtpAgent,
{appviewClient, chatClient}: LinkResolvers,
uri: string,
): Promise<ResolvedLink> {
if (isShortLink(uri)) {
@@ -124,15 +139,17 @@ export async function resolveLink(
const [_0, handleOrDid, _1, rkey] = uri.split('/').filter(Boolean)
const did = await fetchDid(handleOrDid)
const feed = makeRecordUri(did, 'app.bsky.feed.generator', rkey)
const res = await agent.app.bsky.feed.getFeedGenerator({feed})
const data = await appviewClient.call(app.bsky.feed.getFeedGenerator, {
feed: feed,
})
return {
type: 'record',
record: {
uri: res.data.view.uri,
cid: res.data.view.cid,
uri: data.view.uri,
cid: data.view.cid,
},
kind: 'feed',
view: res.data.view,
view: data.view,
}
}
if (isBskyListUrl(uri)) {
@@ -140,28 +157,29 @@ export async function resolveLink(
const [_0, handleOrDid, _1, rkey] = uri.split('/').filter(Boolean)
const did = await fetchDid(handleOrDid)
const list = makeRecordUri(did, 'app.bsky.graph.list', rkey)
const res = await agent.app.bsky.graph.getList({list})
const data = await appviewClient.call(app.bsky.graph.getList, {
list: list,
})
return {
type: 'record',
record: {
uri: res.data.list.uri,
cid: res.data.list.cid,
uri: data.list.uri,
cid: data.list.cid,
},
kind: 'list',
view: res.data.list,
view: data.list,
}
}
const chatInviteCode = getChatInviteCodeFromUrl(uri)
if (chatInviteCode) {
const res = await agent.chat.bsky.group.getJoinLinkPreviews(
{codes: [chatInviteCode]},
{headers: DM_SERVICE_HEADERS},
)
const data = await chatClient.call(chat.bsky.group.getJoinLinkPreviews, {
codes: [chatInviteCode],
})
return {
type: 'chat-invite',
uri,
code: chatInviteCode,
view: res.data.joinLinkPreviews[0],
view: data.joinLinkPreviews[0],
}
}
if (isBskyStartUrl(uri) || isBskyStarterPackUrl(uri)) {
@@ -173,15 +191,17 @@ export async function resolveLink(
}
const did = await fetchDid(parsed.name)
const starterPack = createStarterPackUri({did, rkey: parsed.rkey})
const res = await agent.app.bsky.graph.getStarterPack({starterPack})
const data = await appviewClient.call(app.bsky.graph.getStarterPack, {
starterPack: starterPack as AtUriString,
})
return {
type: 'record',
record: {
uri: res.data.starterPack.uri,
cid: res.data.starterPack.cid,
uri: data.starterPack.uri,
cid: data.starterPack.cid,
},
kind: 'starter-pack',
view: res.data.starterPack,
view: data.starterPack,
}
}
return resolveExternal(uri)
@@ -190,17 +210,17 @@ export async function resolveLink(
async function getPost({uri}: {uri: string}) {
const urip = new AtUri(uri)
if (!urip.host.startsWith('did:')) {
const res = await agent.resolveHandle({
handle: urip.host,
})
// @ts-expect-error TODO new-sdk-migration
urip.host = res.data.did
const data = await appviewClient.call(
com.atproto.identity.resolveHandle,
{handle: urip.host as HandleString},
)
urip.host = data.did
}
const res = await agent.getPosts({
const data = await appviewClient.call(app.bsky.feed.getPosts, {
uris: [urip.toString()],
})
if (res.success && res.data.posts[0]) {
return res.data.posts[0]
if (data.posts[0]) {
return data.posts[0]
}
throw new Error('getPost: post not found')
}
@@ -209,17 +229,17 @@ export async function resolveLink(
async function fetchDid(handleOrDid: string) {
let identifier = handleOrDid
if (!identifier.startsWith('did:')) {
const res = await agent.resolveHandle({handle: identifier})
identifier = res.data.did
const data = await appviewClient.call(
com.atproto.identity.resolveHandle,
{handle: identifier as HandleString},
)
identifier = data.did
}
return identifier
}
}
export async function resolveGif(
agent: AtpAgent,
gif: Gif,
): Promise<ResolvedExternalLink> {
export async function resolveGif(gif: Gif): Promise<ResolvedExternalLink> {
const gifUrl = gif.media_formats.gif.url
const params = new URLSearchParams()
params.set('hh', String(gif.media_formats.gif.dims[1]))