birdclaw 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +92 -1
- package/README.md +75 -5
- package/package.json +8 -2
- package/scripts/browser-perf.mjs +1 -0
- package/scripts/start-test-server.mjs +16 -3
- package/src/cli.ts +812 -37
- package/src/components/AccountSwitcher.tsx +186 -0
- package/src/components/AppNav.tsx +37 -7
- package/src/components/AvatarChip.tsx +9 -3
- package/src/components/DmWorkspace.tsx +18 -8
- package/src/components/LinkPreviewCard.tsx +40 -18
- package/src/components/MarkdownViewer.tsx +818 -0
- package/src/components/ProfileAnalysisStream.tsx +428 -0
- package/src/components/ProfilePreview.tsx +120 -9
- package/src/components/SavedTimelineView.tsx +30 -8
- package/src/components/SyncNowButton.tsx +60 -25
- package/src/components/ThemeSlider.tsx +55 -50
- package/src/components/TimelineCard.tsx +240 -92
- package/src/components/TimelineRouteFrame.tsx +38 -8
- package/src/components/TweetMediaGrid.tsx +87 -38
- package/src/components/TweetRichText.tsx +45 -17
- package/src/components/account-selection.ts +64 -0
- package/src/components/useTimelineRouteData.ts +97 -13
- package/src/lib/account-sync-job.ts +666 -0
- package/src/lib/actions-transport.ts +216 -146
- package/src/lib/api-client.ts +128 -53
- package/src/lib/archive-finder.ts +78 -63
- package/src/lib/archive-import.ts +1593 -1291
- package/src/lib/authored-live.ts +262 -204
- package/src/lib/avatar-cache.ts +208 -43
- package/src/lib/backup.ts +1536 -954
- package/src/lib/bird-actions.ts +139 -57
- package/src/lib/bird-command.ts +101 -28
- package/src/lib/bird.ts +582 -194
- package/src/lib/blocklist.ts +40 -23
- package/src/lib/blocks-write.ts +129 -80
- package/src/lib/blocks.ts +165 -97
- package/src/lib/bookmark-sync-job.ts +250 -160
- package/src/lib/config.ts +35 -2
- package/src/lib/conversation-surface.ts +79 -48
- package/src/lib/data-sources.ts +219 -0
- package/src/lib/db.ts +95 -4
- package/src/lib/dms-live.ts +720 -66
- package/src/lib/effect-runtime.ts +45 -0
- package/src/lib/follow-graph.ts +224 -180
- package/src/lib/geocoding.ts +296 -0
- package/src/lib/http-effect.ts +222 -0
- package/src/lib/inbox.ts +74 -43
- package/src/lib/link-index.ts +88 -76
- package/src/lib/link-insights.ts +24 -0
- package/src/lib/link-preview-metadata.ts +472 -52
- package/src/lib/location.ts +137 -0
- package/src/lib/media-fetch.ts +286 -213
- package/src/lib/mention-threads-live.ts +445 -288
- package/src/lib/mentions-live.ts +549 -354
- package/src/lib/moderation-target.ts +102 -65
- package/src/lib/moderation-write.ts +77 -18
- package/src/lib/mutes-write.ts +129 -80
- package/src/lib/mutes.ts +8 -1
- package/src/lib/network-map.ts +382 -0
- package/src/lib/openai.ts +84 -53
- package/src/lib/period-digest.ts +1317 -0
- package/src/lib/profile-affiliation-hydration.ts +93 -54
- package/src/lib/profile-analysis.ts +1272 -0
- package/src/lib/profile-bio-entities.ts +1 -1
- package/src/lib/profile-hydration.ts +124 -72
- package/src/lib/profile-replies.ts +60 -43
- package/src/lib/profile-resolver.ts +402 -294
- package/src/lib/queries.ts +983 -203
- package/src/lib/research.ts +165 -120
- package/src/lib/search-discussion.ts +1016 -0
- package/src/lib/sqlite.ts +1 -0
- package/src/lib/timeline-collections-live.ts +204 -167
- package/src/lib/timeline-live.ts +325 -51
- package/src/lib/tweet-account-edges.ts +2 -0
- package/src/lib/tweet-lookup.ts +30 -19
- package/src/lib/tweet-render.ts +141 -1
- package/src/lib/tweet-search-live.ts +565 -0
- package/src/lib/types.ts +75 -3
- package/src/lib/ui.ts +31 -8
- package/src/lib/url-expansion.ts +226 -55
- package/src/lib/url-safety.ts +220 -0
- package/src/lib/web-sync.ts +222 -149
- package/src/lib/whois.ts +166 -147
- package/src/lib/x-web.ts +102 -71
- package/src/lib/xurl-rate-limits.ts +267 -0
- package/src/lib/xurl.ts +1185 -405
- package/src/routeTree.gen.ts +273 -0
- package/src/routes/__root.tsx +24 -5
- package/src/routes/api/action.tsx +127 -78
- package/src/routes/api/avatar.tsx +39 -30
- package/src/routes/api/blocks.tsx +26 -23
- package/src/routes/api/conversation.tsx +25 -14
- package/src/routes/api/data-sources.tsx +24 -0
- package/src/routes/api/inbox.tsx +27 -21
- package/src/routes/api/link-insights.tsx +31 -25
- package/src/routes/api/link-preview.tsx +25 -21
- package/src/routes/api/network-map.tsx +55 -0
- package/src/routes/api/period-digest.tsx +133 -0
- package/src/routes/api/profile-analysis.tsx +152 -0
- package/src/routes/api/profile-hydrate.tsx +31 -28
- package/src/routes/api/query.tsx +80 -55
- package/src/routes/api/search-discussion.tsx +169 -0
- package/src/routes/api/status.tsx +18 -10
- package/src/routes/api/sync.tsx +75 -29
- package/src/routes/api/xurl-rate-limits.tsx +24 -0
- package/src/routes/data-sources.tsx +255 -0
- package/src/routes/discuss.tsx +419 -0
- package/src/routes/dms.tsx +95 -28
- package/src/routes/inbox.tsx +32 -19
- package/src/routes/network-map.tsx +1035 -0
- package/src/routes/profile-analyze.tsx +112 -0
- package/src/routes/profiles.$handle.tsx +228 -0
- package/src/routes/rate-limits.tsx +309 -0
- package/src/routes/today.tsx +455 -0
- package/src/styles.css +22 -0
package/src/routes/inbox.tsx
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { createFileRoute } from "@tanstack/react-router";
|
|
2
2
|
import { Sparkles } from "lucide-react";
|
|
3
3
|
import { useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { useSelectedAccountId } from "#/components/account-selection";
|
|
4
5
|
import { InboxCard } from "#/components/InboxCard";
|
|
6
|
+
import { postAction } from "#/lib/api-client";
|
|
5
7
|
import type {
|
|
6
8
|
InboxItem,
|
|
7
9
|
InboxKind,
|
|
@@ -48,7 +50,9 @@ function InboxRoute() {
|
|
|
48
50
|
const [activeReplyId, setActiveReplyId] = useState<string | null>(null);
|
|
49
51
|
const [replyDraft, setReplyDraft] = useState("");
|
|
50
52
|
const [isSendingReply, setIsSendingReply] = useState(false);
|
|
53
|
+
const [replyError, setReplyError] = useState<string | null>(null);
|
|
51
54
|
const [stats, setStats] = useState<InboxResponse["stats"] | null>(null);
|
|
55
|
+
const selectedAccountId = useSelectedAccountId(meta?.accounts);
|
|
52
56
|
|
|
53
57
|
useEffect(() => {
|
|
54
58
|
fetch("/api/status")
|
|
@@ -61,6 +65,9 @@ function InboxRoute() {
|
|
|
61
65
|
url.searchParams.set("kind", kind);
|
|
62
66
|
url.searchParams.set("minScore", minScore);
|
|
63
67
|
url.searchParams.set("refresh", String(refreshTick));
|
|
68
|
+
if (selectedAccountId) {
|
|
69
|
+
url.searchParams.set("account", selectedAccountId);
|
|
70
|
+
}
|
|
64
71
|
if (hideLowSignal) {
|
|
65
72
|
url.searchParams.set("hideLowSignal", "1");
|
|
66
73
|
}
|
|
@@ -71,7 +78,7 @@ function InboxRoute() {
|
|
|
71
78
|
setItems(data.items);
|
|
72
79
|
setStats(data.stats);
|
|
73
80
|
});
|
|
74
|
-
}, [hideLowSignal, kind, minScore, refreshTick]);
|
|
81
|
+
}, [hideLowSignal, kind, minScore, refreshTick, selectedAccountId]);
|
|
75
82
|
|
|
76
83
|
const subtitle = useMemo(() => {
|
|
77
84
|
if (!meta || !stats) return "Ranking unreplied mentions and DMs...";
|
|
@@ -87,6 +94,7 @@ function InboxRoute() {
|
|
|
87
94
|
body: JSON.stringify({
|
|
88
95
|
kind: "scoreInbox",
|
|
89
96
|
scoreKind: kind,
|
|
97
|
+
account: selectedAccountId,
|
|
90
98
|
limit: 8,
|
|
91
99
|
}),
|
|
92
100
|
});
|
|
@@ -99,28 +107,27 @@ function InboxRoute() {
|
|
|
99
107
|
async function sendReply(item: InboxItem) {
|
|
100
108
|
if (!replyDraft.trim()) return;
|
|
101
109
|
setIsSendingReply(true);
|
|
110
|
+
setReplyError(null);
|
|
102
111
|
try {
|
|
103
|
-
await
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
text: replyDraft,
|
|
118
|
-
},
|
|
119
|
-
),
|
|
120
|
-
});
|
|
112
|
+
await postAction(
|
|
113
|
+
item.entityKind === "dm"
|
|
114
|
+
? {
|
|
115
|
+
kind: "replyDm",
|
|
116
|
+
conversationId: item.entityId,
|
|
117
|
+
text: replyDraft,
|
|
118
|
+
}
|
|
119
|
+
: {
|
|
120
|
+
kind: "replyTweet",
|
|
121
|
+
accountId: item.accountId,
|
|
122
|
+
tweetId: item.entityId,
|
|
123
|
+
text: replyDraft,
|
|
124
|
+
},
|
|
125
|
+
);
|
|
121
126
|
setReplyDraft("");
|
|
122
127
|
setActiveReplyId(null);
|
|
123
128
|
setRefreshTick((value) => value + 1);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
setReplyError(error instanceof Error ? error.message : "Reply failed");
|
|
124
131
|
} finally {
|
|
125
132
|
setIsSendingReply(false);
|
|
126
133
|
}
|
|
@@ -181,6 +188,11 @@ function InboxRoute() {
|
|
|
181
188
|
})}
|
|
182
189
|
</div>
|
|
183
190
|
</header>
|
|
191
|
+
{replyError ? (
|
|
192
|
+
<p className={cx(timestampClass, "px-4 py-2 text-red-500")}>
|
|
193
|
+
{replyError}
|
|
194
|
+
</p>
|
|
195
|
+
) : null}
|
|
184
196
|
<section className={feedClass}>
|
|
185
197
|
{items.length === 0 ? (
|
|
186
198
|
<div className={emptyStateClass}>Inbox clear.</div>
|
|
@@ -193,6 +205,7 @@ function InboxRoute() {
|
|
|
193
205
|
onReplyChange={setReplyDraft}
|
|
194
206
|
onReplySend={() => void sendReply(item)}
|
|
195
207
|
onReplyToggle={() => {
|
|
208
|
+
setReplyError(null);
|
|
196
209
|
if (activeReplyId === item.id) {
|
|
197
210
|
setActiveReplyId(null);
|
|
198
211
|
setReplyDraft("");
|