Sign in
Join now
scn-chat
sharedcomputer.network
/
Star
Starred
Star
Something went wrong. Try again.
Fork
0
Eye filled
Watch
Watching
Watch
ATProto-based AI Assistant Chat interface.
Star
Starred
Star
Something went wrong. Try again.
Fork
Eye filled
Watch
Watching
Watch
Overview
Overview
Issues
Issues
1
1
Pulls
Pulls
Pipelines
Pipelines
scn-chat
/
apps
/
web
/
tests
6 folders
·
2 files
at
rate-limits
hadsie.com
·
Retry busy providers. Don't retry spent keys. Add messaging for users.
·
2w ago
dead7601
features
Retry busy providers. Don't retry spent keys. Add messaging for users.
2w ago
helpers
The reply follower, in features/conversation/reply-follower.ts, follows each pending reply in the open conversation until its final record arrives, in place of replyStreamQuery in queries.ts, useReplyStream, and the stream logic in ReplyStream, LiveAuthor, and ConversationView. useReplyFollower(skey, messages) works out the pending replies from the records and returns follow for a reply just sent, and owns the stream queries, when each stream has ended, the poll with its backoff, and the refresh once a reply finishes. A reply's views read it without ever starting a stream: useFollowedReply gives what has streamed and why the reply is no longer live, dropped or elsewhere, and useReplyStarted rerenders the header only once the reply starts. The stream query and the finished statuses are private to it, so a view can no longer start a stream by leaving out enabled: false. Behaviour is unchanged. Its tests, over a shared fake EventSource in tests/helpers, cover the stream, following before the record arrives, a dropped or unreadable stream, the poll, another server running the reply, closing, and that deltas rerender neither the conversation nor the header, in place of the poll and stream tests in ConversationView's tests and replyEvents's own. The web UI spec's streaming section describes it, and the glossary names it.
2w ago
parts
A footnote link scrolls to its note in the same reply rather than opening the page in a new tab, and the note's way back does the same. Every reply numbers its footnotes from one, so their ids repeat down the page and a plain jump would land in the first reply's notes; the link looks for its target inside its own reply instead. Streamdown's hardening gives every link a new tab, so a link within the text drops it. Other links still open in a new tab. The web UI spec says so, and the Markdown test renders two replies with the same footnote and checks the jump stays in the one clicked.
2w ago
shared
A Select given searchLabel opens a list of eight options or more, about as many as it shows before scrolling, with a search box named by it, and the model select gives "Search models", which finds a model by its name, its ID, or its provider through the options' new keywords. The box takes the focus as the list opens, except on a touch screen, where it waits for a tap so its keyboard doesn't cover the list. Typing narrows the options to those holding every word typed, in any case, moves to the first that matches, and says "No matches" through a status that is there from the start, so screen readers hear it. The arrow keys, Page Up, Page Down, and Enter work from the box while Home, End, and Space stay the field's, Escape closes the list and Tab moves on, each from the button, which takes the focus back as after a pick, and a letter typed on the closed button opens the list searching for it. An option's id comes from its place among every option, so the active id changes with each move and screen readers and the scroll into view follow it. The list's heading and search box sit over the options, which alone scroll, and usePlacement measures the room the reader can see, following the visual viewport as an on-screen keyboard comes and goes. touchOnly is shared with the composer from shared/touch.ts. The styling and web UI specs describe it, with tests and an acceptance criterion.
2w ago
store
The browser store's React module keeps its query keys and its worker to itself and offers intents in their place: useRefreshConversation, and refreshConversation for a query's own function, check an open conversation against the PDS again as opening it does, and useSyncIndex syncs the chat index. The composer, the conversation actions, the reply follower, the chat list, and the sync status use them, so conversationRefreshKey is no longer exported and nothing outside src/store reaches the worker. The reply follower's poll now checks the conversation as opening it does, refreshing and then reconciling, so a refresh means one thing everywhere, and its key moves to reply-poll, leaving the conversation prefix to the store's own queries, whose exact invalidation on a change is commented and tested. useConversation gives waiting and empty in place of isLoading, refreshed, and refreshing, so ConversationView no longer works out when a conversation is known. The store's hooks have their own tests, and the web UI spec describes them.
2w ago
styles
Finish the styling port by deleting main's stand-in sheet, its legacy layer, and every data-ported marker, so every element's look is its own utilities over the theme. The shared chat page, which leaned on the old sheet, gets the conversation's column with its title and who shared it above the messages, and its sign-in and loading states center on the panel. Copy's icon swap and the Jump to button stop scaling under reduced motion. The architecture doc describes the token theme and Streamdown and lists ADRs 0004 and 0005, the web UI spec no longer calls the app plain, the styling spec marks the port done and ticks the criteria checked, and the extending spec records what the styling port already delivered.
2w ago
App.test.tsx
The sign-in field suggests accounts as you type a handle, from Bluesky's public searchActorsTypeahead, which the browser asks itself without a referrer after a 150 ms pause, skipping a DID or PDS URL. Each suggestion shows the account's avatar thumbnail, display name, and handle, and picking one by click or with the arrow keys and Enter fills in its handle, with its avatar in place of the @ until the field is edited, while Enter with nothing picked signs in as before. The panel shows skeleton rows once a first search takes the quiet wait, keeps the last accounts with a spinner in the field while a later one loads, and says when nothing matches or the search failed, with a hint to type the full handle, and screen readers hear how many accounts were found. The login page preconnects to the typeahead and Bluesky's image CDN, the field turns off the browser's own autocomplete, and Avatar is its own component, shared with the account card. The auth spec describes it, with tests and acceptance criteria.
2w ago
setup.ts
Port the composer from design-reference. It is one card stuck to the panel's foot over a fade, with quotes and attachment chips at its top, a box that grows with its text and clears from its corner, and a toolbar of Attach, one quiet select for the model and its thinking effort in a submenu with timer pies, and Send, which Stop replaces while a reply runs. Files paste or drop anywhere on the conversation, Enter doesn't send on touch or while an input method composes, editing shows a banner, More quotes a reply into it, and a button above it jumps to the latest message. New chat goes to /, an empty conversation with starters whose first message creates the chat, reusing it when a send is tried again. The last effort is kept on the device, and ModelSelect and EffortSelect move onto the app's Select.
2w ago