birdclaw 0.8.4 → 0.9.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +22 -2
  3. package/dist/cli/birdclaw.js +1233 -192
  4. package/dist/client/assets/AvatarChip-C8zELEVt.js +1 -0
  5. package/dist/client/assets/ProfilePreview-CsiLpFrb.js +1 -0
  6. package/dist/client/assets/SavedTimelineView-DE4CXK-h.js +1 -0
  7. package/dist/client/assets/SmartTimestamp-BypN4KPq.js +1 -0
  8. package/dist/client/assets/TimelineRouteFrame-D6djyMAT.js +1 -0
  9. package/dist/client/assets/blocks-h27nF3TL.js +1 -0
  10. package/dist/client/assets/{bookmarks-CbBkMvXk.js → bookmarks-Cprrli-V.js} +1 -1
  11. package/dist/client/assets/circle-check-BCK_qvXt.js +1 -0
  12. package/dist/client/assets/client-stream-contracts-D1QUdWfh.js +5 -0
  13. package/dist/client/assets/createLucideIcon-CMLcIxOz.js +1 -0
  14. package/dist/client/assets/data-sources-Beb3JZkl.js +1 -0
  15. package/dist/client/assets/discuss-ciwVz7Fo.js +1 -0
  16. package/dist/client/assets/dms-BZ3GUPey.js +1 -0
  17. package/dist/client/assets/inbox-Dajdut79.js +1 -0
  18. package/dist/client/assets/index-a1ZAcWSa.js +31 -0
  19. package/dist/client/assets/likes-CxZZqiZC.js +1 -0
  20. package/dist/client/assets/links-CsWS9uKL.js +1 -0
  21. package/dist/client/assets/mapbox-dx7h2mOm.js +2 -0
  22. package/dist/client/assets/{mapbox-gl-dgf_hX3a.js → mapbox-gl-WUhsQcSS.js} +1 -1
  23. package/dist/client/assets/{mentions-CxKCgzIf.js → mentions-C3JYXV2K.js} +1 -1
  24. package/dist/client/assets/network-map-D4XA7TTO.js +2 -0
  25. package/dist/client/assets/profile-analyze-QAznTMjZ.js +1 -0
  26. package/dist/client/assets/{profile-hydration-client-YEtJsNTv.js → profile-hydration-client-BQyC5--e.js} +1 -1
  27. package/dist/client/assets/profiles._handle-qntfbCE1.js +1 -0
  28. package/dist/client/assets/query-client-DZ5C7UNo.js +17 -0
  29. package/dist/client/assets/rate-limits-eHs_5dDB.js +1 -0
  30. package/dist/client/assets/react-BwGzW7mM.js +1 -0
  31. package/dist/client/assets/react-dom-DEMAB80t.js +1 -0
  32. package/dist/client/assets/{repeat-2-xCwHM9hD.js → repeat-2-CQ0lek01.js} +1 -1
  33. package/dist/client/assets/rolldown-runtime-B-9mzPXz.js +1 -0
  34. package/dist/client/assets/{routes-q7ZaW4En.js → routes-CeIv5bkV.js} +1 -1
  35. package/dist/client/assets/schemas-CntsNLmN.js +64 -0
  36. package/dist/client/assets/search-C_LqodNa.js +1 -0
  37. package/dist/client/assets/{sparkles-CQVlvHsZ.js → sparkles-Gx_BHkDX.js} +1 -1
  38. package/dist/client/assets/styles-DTMajAmk.css +2 -0
  39. package/dist/client/assets/today-DxppbQGF.js +1 -0
  40. package/dist/client/assets/{triangle-alert-CBL7s2pf.js → triangle-alert-DJPCW6jQ.js} +1 -1
  41. package/dist/client/assets/useTimelineRouteData-CWvBmHLE.js +1 -0
  42. package/dist/client/assets/{users-CHbKlqUr.js → users-DI3w8Mol.js} +1 -1
  43. package/dist/server/assets/{AvatarChip-zUDAEmjL.js → AvatarChip-DWag3IzT.js} +1 -1
  44. package/dist/server/assets/{FeedState-ntW0Q2GB.js → FeedState-CwzcvP-p.js} +1 -1
  45. package/dist/server/assets/{ProfileAnalysisStream-BFvhVdhn.js → ProfileAnalysisStream-CLjrYzEx.js} +2 -2
  46. package/dist/server/assets/{ProfilePreview-C6gAor_j.js → ProfilePreview-Bq-DSUM2.js} +7 -8
  47. package/dist/server/assets/{SavedTimelineView-BG1jnBp1.js → SavedTimelineView-Bk9nfnb-.js} +2 -2
  48. package/dist/server/assets/{SmartTimestamp-DfwE1NGf.js → SmartTimestamp-C06w_f9J.js} +1 -1
  49. package/dist/server/assets/SyncNowButton-CKuXKYcd.js +259 -0
  50. package/dist/server/assets/{TimelineRouteFrame-CU7ilM7U.js → TimelineRouteFrame-Bg3e7X_N.js} +5 -3
  51. package/dist/server/assets/{TweetRichText-DhCVv1-6.js → TweetRichText-wzUAtbPS.js} +2 -2
  52. package/dist/server/assets/{_tanstack-start-manifest_v-C-ZRnG_n.js → _tanstack-start-manifest_v-CjYYXQ8Z.js} +35 -35
  53. package/dist/server/assets/{blocks-DSgQghqP.js → blocks-CaP_u3mY.js} +3 -3
  54. package/dist/server/assets/{blocks-C1mgGTB3.js → blocks-DKy4yTF-.js} +3 -3
  55. package/dist/server/assets/{bookmarks-BJN8tykY.js → bookmarks-CPFq3JVX.js} +1 -1
  56. package/dist/server/assets/{client-stream-contracts-C2xbWVjm.js → client-stream-contracts-gtXEreFY.js} +72 -8
  57. package/dist/server/assets/{data-sources-BnA1Q94p.js → data-sources-DWwmQqcO.js} +1 -1
  58. package/dist/server/assets/{discuss-CJ1dau1j.js → discuss-BB8wFy4L.js} +3 -3
  59. package/dist/server/assets/{discuss-QTo08NCN.js → discuss-CVGB4_I0.js} +3 -3
  60. package/dist/server/assets/{dms-DAyQrVM2.js → dms-7NzdyQZQ.js} +6 -6
  61. package/dist/server/assets/{dms-BuLj4bp8.js → dms-vbEumuuO.js} +4 -4
  62. package/dist/server/assets/{empty-plugin-adapters-DzrEkdBF.js → empty-plugin-adapters-D9UWiqvJ.js} +1 -1
  63. package/dist/server/assets/{inbox-CkGOaW1q.js → inbox-CBeZctFd.js} +2 -2
  64. package/dist/server/assets/{inbox-DpWd1EzC.js → inbox-UpHhXODd.js} +4 -4
  65. package/dist/server/assets/{likes-DBOAtsJU.js → likes-CDAjYyTm.js} +1 -1
  66. package/dist/server/assets/{links-DAhSjynu.js → links-DU-TIHtg.js} +6 -6
  67. package/dist/server/assets/{links-DmH5lxHO.js → links-sQ3q2jvO.js} +6 -6
  68. package/dist/server/assets/{mentions-BH2MzKtB.js → mentions-DdndGSRw.js} +1 -1
  69. package/dist/server/assets/{network-map-D3CzRcC4.js → network-map-B9iOapuB.js} +2 -2
  70. package/dist/server/assets/{network-map-D5DoLOwR.js → network-map-CcOz-T9O.js} +2 -2
  71. package/dist/server/assets/{profile-analyze-C1NoM0tV.js → profile-analyze-BmDeTif5.js} +1 -1
  72. package/dist/server/assets/{profile-analyze-BP65PED0.js → profile-analyze-CUfXmXEH.js} +3 -3
  73. package/dist/server/assets/{profiles._handle-DsLNj2Ca.js → profiles._handle-8snagiR1.js} +4 -4
  74. package/dist/server/assets/{profiles._handle-DjwlN_ac.js → profiles._handle-BAqnghwo.js} +5 -5
  75. package/dist/server/assets/{rate-limits-VAr2qzYD.js → rate-limits-BY2-aQPT.js} +1 -1
  76. package/dist/server/assets/{router-DqkwSPiM.js → router-DP7iZD-q.js} +424 -128
  77. package/dist/server/assets/{routes-A9c9ZhwN.js → routes-D9226vKz.js} +1 -1
  78. package/dist/server/assets/start-5Z2QO8AU.js +4 -0
  79. package/dist/server/assets/{today-B5hVM57Z.js → today-BmvIMJzI.js} +3 -3
  80. package/dist/server/assets/{today-fvGiZ7ud.js → today-DKWphGrC.js} +112 -57
  81. package/dist/server/assets/{ui-qbmcMSSX.js → ui-rDHeS-cc.js} +2 -1
  82. package/dist/server/assets/{useTimelineRouteData-27cxynxa.js → useTimelineRouteData-BmDbGvQ8.js} +7 -7
  83. package/dist/server/server.js +50 -3413
  84. package/package.json +13 -13
  85. package/dist/client/assets/AvatarChip-DLoqM5xD.js +0 -1
  86. package/dist/client/assets/ProfilePreview-BejAuYsJ.js +0 -1
  87. package/dist/client/assets/SavedTimelineView-BIS7HKpp.js +0 -1
  88. package/dist/client/assets/SmartTimestamp-BR0-9se2.js +0 -1
  89. package/dist/client/assets/TimelineRouteFrame-CyGPj0eM.js +0 -1
  90. package/dist/client/assets/blocks-7UDKQp8H.js +0 -1
  91. package/dist/client/assets/chunk-C0phanGV.js +0 -1
  92. package/dist/client/assets/circle-check-C_Vq3ElD.js +0 -1
  93. package/dist/client/assets/client-stream-contracts-ys3XhWG4.js +0 -5
  94. package/dist/client/assets/createLucideIcon-JV8isFFR.js +0 -1
  95. package/dist/client/assets/data-sources-Cm2bpNvg.js +0 -1
  96. package/dist/client/assets/discuss-DTjaOugw.js +0 -1
  97. package/dist/client/assets/dms-CGd6Eogq.js +0 -1
  98. package/dist/client/assets/inbox-BHlGuOy2.js +0 -1
  99. package/dist/client/assets/index-CEIG7S6s.js +0 -31
  100. package/dist/client/assets/likes-cLrcAQem.js +0 -1
  101. package/dist/client/assets/links-CM9QO1LC.js +0 -1
  102. package/dist/client/assets/mapbox-BxTlqXt9.js +0 -2
  103. package/dist/client/assets/network-map-B5a3whqj.js +0 -2
  104. package/dist/client/assets/profile-analyze-CRtNEwlb.js +0 -1
  105. package/dist/client/assets/profiles._handle-C82_HoKX.js +0 -1
  106. package/dist/client/assets/query-client-fYu2rzRC.js +0 -17
  107. package/dist/client/assets/rate-limits-ScaEwdVK.js +0 -1
  108. package/dist/client/assets/react-dom-DHl6Ug7F.js +0 -1
  109. package/dist/client/assets/react-nBylq1U5.js +0 -1
  110. package/dist/client/assets/schemas-I9r6F6ya.js +0 -64
  111. package/dist/client/assets/search-Dq5kYsxA.js +0 -1
  112. package/dist/client/assets/styles-B8s3tt3r.css +0 -2
  113. package/dist/client/assets/today-CeG1O7Py.js +0 -1
  114. package/dist/client/assets/useTimelineRouteData-1HsqgvUi.js +0 -1
  115. package/dist/server/assets/SyncNowButton-BOn_IBXS.js +0 -76
  116. package/dist/server/assets/start-FaDOTmto.js +0 -4
@@ -0,0 +1,259 @@
1
+ import { Yt as selectFieldClass, m as cx } from "./ui-rDHeS-cc.js";
2
+ import { c as postSync } from "./query-client-BdauHBgd.js";
3
+ import { n as setStoredAccountId, r as useSelectedAccountId, t as defaultAccountId } from "./account-selection-CTdFGWRk.js";
4
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
+ import { RefreshCw } from "lucide-react";
7
+ //#region src/components/SyncNowButton.tsx
8
+ var AUTO_SYNC_INTERVALS = [
9
+ {
10
+ label: "5m",
11
+ value: 5 * 6e4
12
+ },
13
+ {
14
+ label: "10m",
15
+ value: 10 * 6e4
16
+ },
17
+ {
18
+ label: "15m",
19
+ value: 15 * 6e4
20
+ },
21
+ {
22
+ label: "30m",
23
+ value: 30 * 6e4
24
+ },
25
+ {
26
+ label: "1h",
27
+ value: 60 * 6e4
28
+ }
29
+ ];
30
+ var DEFAULT_AUTO_SYNC_INTERVAL_MS = 10 * 6e4;
31
+ var MAX_AUTO_SYNC_BACKOFF_MS = 60 * 6e4;
32
+ function autoSyncStorageKey(kind, accountId) {
33
+ return `birdclaw:auto-sync:${kind}:${accountId ?? "default"}`;
34
+ }
35
+ function validAutoSyncInterval(value) {
36
+ return AUTO_SYNC_INTERVALS.some((option) => option.value === value);
37
+ }
38
+ function readAutoSyncSettings(key) {
39
+ try {
40
+ const value = JSON.parse(window.localStorage.getItem(key) ?? "null");
41
+ return {
42
+ enabled: value?.enabled === true,
43
+ intervalMs: validAutoSyncInterval(value?.intervalMs) ? value.intervalMs : DEFAULT_AUTO_SYNC_INTERVAL_MS
44
+ };
45
+ } catch {
46
+ return {
47
+ enabled: false,
48
+ intervalMs: DEFAULT_AUTO_SYNC_INTERVAL_MS
49
+ };
50
+ }
51
+ }
52
+ function SyncNowButton({ kind, label, accounts, onSynced, allowAutoSync = false, autoSyncBlocked = false, showAccountPicker = false, syncOptions }) {
53
+ const [syncing, setSyncing] = useState(false);
54
+ const [message, setMessage] = useState(null);
55
+ const [error, setError] = useState(null);
56
+ const syncingRef = useRef(false);
57
+ const onSyncedRef = useRef(onSynced);
58
+ const [autoSyncing, setAutoSyncing] = useState(false);
59
+ const [autoSyncError, setAutoSyncError] = useState(null);
60
+ const [autoFailureCount, setAutoFailureCount] = useState(0);
61
+ const [autoCycle, setAutoCycle] = useState(0);
62
+ const [lastAutoSyncedAt, setLastAutoSyncedAt] = useState(null);
63
+ const [nextAutoSyncAt, setNextAutoSyncAt] = useState(null);
64
+ const accountList = accounts ?? [];
65
+ const globalAccountId = useSelectedAccountId(accounts);
66
+ const defaultAccountId$1 = useMemo(() => defaultAccountId(accounts), [accounts]);
67
+ const accountId = globalAccountId ?? defaultAccountId$1;
68
+ const autoSyncKey = autoSyncStorageKey(kind, accountId);
69
+ const autoSyncKeyRef = useRef(autoSyncKey);
70
+ autoSyncKeyRef.current = autoSyncKey;
71
+ const [autoSettings, setAutoSettings] = useState({
72
+ key: "",
73
+ enabled: false,
74
+ intervalMs: DEFAULT_AUTO_SYNC_INTERVAL_MS
75
+ });
76
+ const autoSettingsReady = autoSettings.key === autoSyncKey;
77
+ const accountAwareSync = kind !== "dms";
78
+ const waitingForAccount = accountAwareSync && accounts === void 0 && (showAccountPicker || kind !== "timeline");
79
+ const birdOnlyWrongAccount = !accountAwareSync && accountId !== void 0 && defaultAccountId$1 !== void 0 && accountId !== defaultAccountId$1;
80
+ const disabled = syncing || waitingForAccount || birdOnlyWrongAccount;
81
+ const statusMessage = birdOnlyWrongAccount ? "Switch to default to sync" : waitingForAccount ? "Loading account" : error ?? message ?? "";
82
+ const autoStatusMessage = autoSyncError ? `Auto sync failed: ${autoSyncError}` : autoSyncing ? "Auto syncing..." : lastAutoSyncedAt ? `Last auto sync ${new Date(lastAutoSyncedAt).toLocaleTimeString()}` : nextAutoSyncAt ? `Next sync ${new Date(nextAutoSyncAt).toLocaleTimeString()}` : autoSettings.enabled ? "Auto sync waiting" : "Auto sync off";
83
+ useEffect(() => {
84
+ onSyncedRef.current = onSynced;
85
+ }, [onSynced]);
86
+ useEffect(() => {
87
+ setAutoSettings({
88
+ key: autoSyncKey,
89
+ ...readAutoSyncSettings(autoSyncKey)
90
+ });
91
+ setAutoSyncError(null);
92
+ setAutoSyncing(false);
93
+ setAutoFailureCount(0);
94
+ setLastAutoSyncedAt(null);
95
+ setNextAutoSyncAt(null);
96
+ setAutoCycle((current) => current + 1);
97
+ }, [autoSyncKey]);
98
+ function selectAccount(accountId) {
99
+ setStoredAccountId(accountId);
100
+ }
101
+ const syncNow = useCallback(async (source) => {
102
+ if (syncingRef.current || waitingForAccount || birdOnlyWrongAccount || source === "auto" && autoSyncBlocked) return false;
103
+ const launchedAutoSyncKey = source === "auto" ? autoSyncKeyRef.current : null;
104
+ syncingRef.current = true;
105
+ setSyncing(true);
106
+ if (source === "auto") {
107
+ setAutoSyncing(true);
108
+ setAutoSyncError(null);
109
+ } else {
110
+ setError(null);
111
+ setMessage(null);
112
+ }
113
+ try {
114
+ const data = await postSync(kind, accountAwareSync ? accountId : void 0, syncOptions);
115
+ if (!data.ok) throw new Error(data.summary);
116
+ if (launchedAutoSyncKey !== null && autoSyncKeyRef.current !== launchedAutoSyncKey) return false;
117
+ if (source === "auto") {
118
+ setLastAutoSyncedAt(Date.now());
119
+ setAutoFailureCount(0);
120
+ } else setMessage(data.summary);
121
+ onSyncedRef.current(data);
122
+ return true;
123
+ } catch (syncError) {
124
+ if (launchedAutoSyncKey !== null && autoSyncKeyRef.current !== launchedAutoSyncKey) return false;
125
+ const syncMessage = syncError instanceof Error ? syncError.message : "Sync failed";
126
+ if (source === "auto") {
127
+ setAutoSyncError(syncMessage);
128
+ setAutoFailureCount((current) => current + 1);
129
+ } else setError(syncMessage);
130
+ return false;
131
+ } finally {
132
+ syncingRef.current = false;
133
+ setSyncing(false);
134
+ if (source === "auto") setAutoSyncing(false);
135
+ }
136
+ }, [
137
+ accountAwareSync,
138
+ accountId,
139
+ autoSyncBlocked,
140
+ birdOnlyWrongAccount,
141
+ kind,
142
+ syncOptions,
143
+ waitingForAccount
144
+ ]);
145
+ useEffect(() => {
146
+ if (!allowAutoSync || !autoSettingsReady || !autoSettings.enabled || autoSyncBlocked || waitingForAccount || birdOnlyWrongAccount) {
147
+ setNextAutoSyncAt(null);
148
+ return;
149
+ }
150
+ const delayMs = Math.min(autoSettings.intervalMs * 2 ** autoFailureCount, MAX_AUTO_SYNC_BACKOFF_MS);
151
+ setNextAutoSyncAt(Date.now() + delayMs);
152
+ const timer = window.setTimeout(() => {
153
+ if (document.visibilityState === "hidden" || syncingRef.current) {
154
+ setAutoCycle((current) => current + 1);
155
+ return;
156
+ }
157
+ syncNow("auto").finally(() => {
158
+ setAutoCycle((current) => current + 1);
159
+ });
160
+ }, delayMs);
161
+ return () => window.clearTimeout(timer);
162
+ }, [
163
+ allowAutoSync,
164
+ autoCycle,
165
+ autoFailureCount,
166
+ autoSettings.enabled,
167
+ autoSettings.intervalMs,
168
+ autoSettingsReady,
169
+ autoSyncBlocked,
170
+ birdOnlyWrongAccount,
171
+ syncNow,
172
+ waitingForAccount
173
+ ]);
174
+ function updateAutoSettings(next) {
175
+ setAutoSettings({
176
+ key: autoSyncKey,
177
+ ...next
178
+ });
179
+ window.localStorage.setItem(autoSyncKey, JSON.stringify({
180
+ enabled: next.enabled,
181
+ intervalMs: next.intervalMs
182
+ }));
183
+ setAutoSyncError(null);
184
+ setAutoFailureCount(0);
185
+ setLastAutoSyncedAt(null);
186
+ setAutoCycle((current) => current + 1);
187
+ }
188
+ return /* @__PURE__ */ jsxs("div", {
189
+ className: cx("flex shrink-0 flex-wrap items-center justify-end gap-2", allowAutoSync && "w-full lg:w-auto"),
190
+ children: [
191
+ showAccountPicker && accountAwareSync && accountList.length > 1 ? /* @__PURE__ */ jsx("select", {
192
+ "aria-label": "Sync account",
193
+ className: cx(selectFieldClass, "h-9 w-[132px]!"),
194
+ disabled: syncing,
195
+ onChange: (event) => selectAccount(event.target.value),
196
+ value: accountId ?? "",
197
+ children: accountList.map((account) => /* @__PURE__ */ jsx("option", {
198
+ value: account.id,
199
+ children: account.handle
200
+ }, account.id))
201
+ }) : null,
202
+ /* @__PURE__ */ jsxs("button", {
203
+ type: "button",
204
+ className: cx("inline-flex h-9 shrink-0 items-center gap-1.5 rounded-full border border-[var(--line)] bg-[var(--bg)] px-3 text-[13px] font-semibold text-[var(--ink)] transition-[background,border-color,color,transform] duration-150 hover:border-[color:color-mix(in_srgb,var(--accent)_45%,var(--line))] hover:bg-[var(--accent-soft)] hover:text-[var(--accent)] active:scale-[0.98] disabled:opacity-65", syncing && "text-[var(--ink-soft)]", birdOnlyWrongAccount ? "disabled:cursor-not-allowed" : "disabled:cursor-wait"),
205
+ "aria-label": birdOnlyWrongAccount ? `${label}: default account only` : syncing ? `${label}: syncing` : label,
206
+ disabled,
207
+ onClick: () => void syncNow("manual"),
208
+ children: [/* @__PURE__ */ jsx(RefreshCw, {
209
+ className: cx("size-4", syncing && "animate-spin"),
210
+ strokeWidth: 2
211
+ }), /* @__PURE__ */ jsx("span", {
212
+ className: "hidden sm:inline",
213
+ children: syncing ? "Syncing..." : label
214
+ })]
215
+ }),
216
+ /* @__PURE__ */ jsx("span", {
217
+ className: cx("hidden max-w-[190px] truncate text-[12px] sm:inline", error ? "text-[var(--alert)]" : "text-[var(--ink-soft)]"),
218
+ role: "status",
219
+ children: statusMessage
220
+ }),
221
+ allowAutoSync && autoSettingsReady ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
222
+ /* @__PURE__ */ jsxs("label", {
223
+ className: "inline-flex h-9 items-center gap-1.5 rounded-full border border-[var(--line)] bg-[var(--bg)] px-2.5 text-[12px] font-medium text-[var(--ink-soft)]",
224
+ children: [/* @__PURE__ */ jsx("input", {
225
+ "aria-label": `Auto sync ${kind}`,
226
+ type: "checkbox",
227
+ checked: autoSettings.enabled,
228
+ disabled: waitingForAccount || birdOnlyWrongAccount,
229
+ onChange: (event) => updateAutoSettings({
230
+ enabled: event.currentTarget.checked,
231
+ intervalMs: autoSettings.intervalMs
232
+ })
233
+ }), "Auto sync"]
234
+ }),
235
+ /* @__PURE__ */ jsx("select", {
236
+ "aria-label": `${label} auto-sync interval`,
237
+ className: cx(selectFieldClass, "h-9 w-[70px]!"),
238
+ disabled: !autoSettings.enabled,
239
+ onChange: (event) => updateAutoSettings({
240
+ enabled: autoSettings.enabled,
241
+ intervalMs: Number(event.currentTarget.value)
242
+ }),
243
+ value: autoSettings.intervalMs,
244
+ children: AUTO_SYNC_INTERVALS.map((option) => /* @__PURE__ */ jsx("option", {
245
+ value: option.value,
246
+ children: option.label
247
+ }, option.value))
248
+ }),
249
+ /* @__PURE__ */ jsx("span", {
250
+ className: cx("max-w-[190px] truncate text-[12px]", autoSyncError ? "text-[var(--alert)]" : "text-[var(--ink-soft)]"),
251
+ role: "status",
252
+ children: autoStatusMessage
253
+ })
254
+ ] }) : null
255
+ ]
256
+ });
257
+ }
258
+ //#endregion
259
+ export { SyncNowButton as t };
@@ -1,6 +1,6 @@
1
- import { cn as tabButtonClass, ln as tabButtonIndicatorClass, m as cx, pn as timestampClass, un as tabStripClass } from "./ui-qbmcMSSX.js";
2
- import { t as SyncNowButton } from "./SyncNowButton-BOn_IBXS.js";
3
- import { a as TimelineSearchField, i as TimelineHeaderSubtitle, n as TimelineFeedHeader, o as TimelineCard, r as TimelineFeedShell, t as useTimelineRouteData } from "./useTimelineRouteData-27cxynxa.js";
1
+ import { dn as tabStripClass, ln as tabButtonClass, m as cx, mn as timestampClass, un as tabButtonIndicatorClass } from "./ui-rDHeS-cc.js";
2
+ import { t as SyncNowButton } from "./SyncNowButton-CKuXKYcd.js";
3
+ import { a as TimelineSearchField, i as TimelineHeaderSubtitle, n as TimelineFeedHeader, o as TimelineCard, r as TimelineFeedShell, t as useTimelineRouteData } from "./useTimelineRouteData-BmDbGvQ8.js";
4
4
  import { useMemo, useState } from "react";
5
5
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/TimelineRouteFrame.tsx
@@ -33,6 +33,8 @@ function TimelineRouteFrame({ title, resource, initialReplyFilter, searchPlaceho
33
33
  subtitles: /* @__PURE__ */ jsx(TimelineHeaderSubtitle, { children: useMemo(() => subtitle(meta), [meta, subtitle]) }),
34
34
  action: /* @__PURE__ */ jsx(SyncNowButton, {
35
35
  accounts: meta?.accounts,
36
+ allowAutoSync: true,
37
+ autoSyncBlocked: loading,
36
38
  kind: syncKind,
37
39
  label: syncLabel,
38
40
  onSynced: refreshLocalView,
@@ -1,5 +1,5 @@
1
- import { hn as tweetLinkClass, mn as tweetHashtagClass, s as bodyCopyClass, vn as tweetMentionClass } from "./ui-qbmcMSSX.js";
2
- import { c as collectTweetSegmentsForText, d as isTweetArticleUrlEntity, f as normalizeTweetUrlEntityRangeForText, s as safeHttpUrl, t as ProfilePreview, u as enrichFallbackUrlEntities } from "./ProfilePreview-C6gAor_j.js";
1
+ import { gn as tweetLinkClass, hn as tweetHashtagClass, s as bodyCopyClass, yn as tweetMentionClass } from "./ui-rDHeS-cc.js";
2
+ import { c as collectTweetSegmentsForText, d as isTweetArticleUrlEntity, f as normalizeTweetUrlEntityRangeForText, s as safeHttpUrl, t as ProfilePreview, u as enrichFallbackUrlEntities } from "./ProfilePreview-Bq-DSUM2.js";
3
3
  import { Fragment } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/components/TweetRichText.tsx
@@ -38,110 +38,110 @@ var tsrStartManifest = () => ({ routes: {
38
38
  ],
39
39
  css: ["/assets/index-bpFrQ5yG.css"],
40
40
  preloads: [
41
- "/assets/index-CEIG7S6s.js",
42
- "/assets/chunk-C0phanGV.js",
43
- "/assets/query-client-fYu2rzRC.js",
44
- "/assets/createLucideIcon-JV8isFFR.js",
45
- "/assets/circle-check-C_Vq3ElD.js",
46
- "/assets/client-stream-contracts-ys3XhWG4.js",
47
- "/assets/sparkles-CQVlvHsZ.js",
48
- "/assets/react-dom-DHl6Ug7F.js",
49
- "/assets/schemas-I9r6F6ya.js",
50
- "/assets/react-nBylq1U5.js",
51
- "/assets/AvatarChip-DLoqM5xD.js",
52
- "/assets/ProfilePreview-BejAuYsJ.js",
53
- "/assets/SmartTimestamp-BR0-9se2.js",
54
- "/assets/profile-hydration-client-YEtJsNTv.js"
41
+ "/assets/index-a1ZAcWSa.js",
42
+ "/assets/rolldown-runtime-B-9mzPXz.js",
43
+ "/assets/react-BwGzW7mM.js",
44
+ "/assets/react-dom-DEMAB80t.js",
45
+ "/assets/schemas-CntsNLmN.js",
46
+ "/assets/createLucideIcon-CMLcIxOz.js",
47
+ "/assets/circle-check-BCK_qvXt.js",
48
+ "/assets/client-stream-contracts-D1QUdWfh.js",
49
+ "/assets/sparkles-Gx_BHkDX.js",
50
+ "/assets/query-client-DZ5C7UNo.js",
51
+ "/assets/AvatarChip-C8zELEVt.js",
52
+ "/assets/ProfilePreview-CsiLpFrb.js",
53
+ "/assets/SmartTimestamp-BypN4KPq.js",
54
+ "/assets/profile-hydration-client-BQyC5--e.js"
55
55
  ],
56
56
  scripts: [{ attrs: {
57
57
  type: "module",
58
58
  async: !0,
59
- src: "/assets/index-CEIG7S6s.js"
59
+ src: "/assets/index-a1ZAcWSa.js"
60
60
  } }]
61
61
  },
62
62
  "/": {
63
63
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/index.tsx",
64
64
  children: void 0,
65
- preloads: ["/assets/routes-q7ZaW4En.js", "/assets/TimelineRouteFrame-CyGPj0eM.js"]
65
+ preloads: ["/assets/routes-CeIv5bkV.js", "/assets/TimelineRouteFrame-D6djyMAT.js"]
66
66
  },
67
67
  "/blocks": {
68
68
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/blocks.tsx",
69
69
  children: void 0,
70
- preloads: ["/assets/blocks-7UDKQp8H.js"]
70
+ preloads: ["/assets/blocks-h27nF3TL.js"]
71
71
  },
72
72
  "/bookmarks": {
73
73
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/bookmarks.tsx",
74
74
  children: void 0,
75
- preloads: ["/assets/bookmarks-CbBkMvXk.js", "/assets/SavedTimelineView-BIS7HKpp.js"]
75
+ preloads: ["/assets/bookmarks-Cprrli-V.js", "/assets/SavedTimelineView-DE4CXK-h.js"]
76
76
  },
77
77
  "/data-sources": {
78
78
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/data-sources.tsx",
79
79
  children: void 0,
80
- preloads: ["/assets/data-sources-Cm2bpNvg.js", "/assets/triangle-alert-CBL7s2pf.js"]
80
+ preloads: ["/assets/data-sources-Beb3JZkl.js", "/assets/triangle-alert-DJPCW6jQ.js"]
81
81
  },
82
82
  "/discuss": {
83
83
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/discuss.tsx",
84
84
  children: void 0,
85
- preloads: ["/assets/discuss-DTjaOugw.js", "/assets/search-Dq5kYsxA.js"]
85
+ preloads: ["/assets/discuss-ciwVz7Fo.js", "/assets/search-C_LqodNa.js"]
86
86
  },
87
87
  "/dms": {
88
88
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/dms.tsx",
89
89
  children: void 0,
90
- preloads: ["/assets/dms-CGd6Eogq.js", "/assets/search-Dq5kYsxA.js"]
90
+ preloads: ["/assets/dms-BZ3GUPey.js", "/assets/search-C_LqodNa.js"]
91
91
  },
92
92
  "/inbox": {
93
93
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/inbox.tsx",
94
94
  children: void 0,
95
- preloads: ["/assets/inbox-BHlGuOy2.js"]
95
+ preloads: ["/assets/inbox-Dajdut79.js"]
96
96
  },
97
97
  "/likes": {
98
98
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/likes.tsx",
99
99
  children: void 0,
100
- preloads: ["/assets/likes-cLrcAQem.js", "/assets/SavedTimelineView-BIS7HKpp.js"]
100
+ preloads: ["/assets/likes-CxZZqiZC.js", "/assets/SavedTimelineView-DE4CXK-h.js"]
101
101
  },
102
102
  "/links": {
103
103
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/links.tsx",
104
104
  children: void 0,
105
105
  preloads: [
106
- "/assets/links-CM9QO1LC.js",
107
- "/assets/repeat-2-xCwHM9hD.js",
108
- "/assets/search-Dq5kYsxA.js",
109
- "/assets/users-CHbKlqUr.js"
106
+ "/assets/links-CsWS9uKL.js",
107
+ "/assets/repeat-2-CQ0lek01.js",
108
+ "/assets/search-C_LqodNa.js",
109
+ "/assets/users-DI3w8Mol.js"
110
110
  ]
111
111
  },
112
112
  "/mentions": {
113
113
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/mentions.tsx",
114
114
  children: void 0,
115
- preloads: ["/assets/mentions-CxKCgzIf.js", "/assets/TimelineRouteFrame-CyGPj0eM.js"]
115
+ preloads: ["/assets/mentions-C3JYXV2K.js", "/assets/TimelineRouteFrame-D6djyMAT.js"]
116
116
  },
117
117
  "/network-map": {
118
118
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/network-map.tsx",
119
119
  children: void 0,
120
120
  preloads: [
121
- "/assets/network-map-B5a3whqj.js",
122
- "/assets/search-Dq5kYsxA.js",
123
- "/assets/users-CHbKlqUr.js"
121
+ "/assets/network-map-D4XA7TTO.js",
122
+ "/assets/search-C_LqodNa.js",
123
+ "/assets/users-DI3w8Mol.js"
124
124
  ]
125
125
  },
126
126
  "/profile-analyze": {
127
127
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/profile-analyze.tsx",
128
128
  children: void 0,
129
- preloads: ["/assets/profile-analyze-CRtNEwlb.js", "/assets/search-Dq5kYsxA.js"]
129
+ preloads: ["/assets/profile-analyze-QAznTMjZ.js", "/assets/search-C_LqodNa.js"]
130
130
  },
131
131
  "/rate-limits": {
132
132
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/rate-limits.tsx",
133
133
  children: void 0,
134
- preloads: ["/assets/rate-limits-ScaEwdVK.js", "/assets/triangle-alert-CBL7s2pf.js"]
134
+ preloads: ["/assets/rate-limits-eHs_5dDB.js", "/assets/triangle-alert-DJPCW6jQ.js"]
135
135
  },
136
136
  "/today": {
137
137
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/today.tsx",
138
138
  children: void 0,
139
- preloads: ["/assets/today-CeG1O7Py.js"]
139
+ preloads: ["/assets/today-DxppbQGF.js"]
140
140
  },
141
141
  "/profiles/$handle": {
142
142
  filePath: "/Users/steipete/Projects/birdclaw/src/routes/profiles.$handle.tsx",
143
143
  children: void 0,
144
- preloads: ["/assets/profiles._handle-C82_HoKX.js"]
144
+ preloads: ["/assets/profiles._handle-qntfbCE1.js"]
145
145
  }
146
146
  } });
147
147
  //#endregion
@@ -1,6 +1,6 @@
1
- import "./ui-qbmcMSSX.js";
1
+ import "./ui-rDHeS-cc.js";
2
2
  import "./query-client-BdauHBgd.js";
3
- import "./AvatarChip-zUDAEmjL.js";
3
+ import "./AvatarChip-DWag3IzT.js";
4
4
  import { t as validateBlocksSearch } from "./route-search-BUlQ5lGM.js";
5
5
  import "./useDebouncedValue-DOnA6Xcy.js";
6
6
  import "react";
@@ -8,7 +8,7 @@ import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
8
8
  import "react/jsx-runtime";
9
9
  import "@tanstack/react-query";
10
10
  //#region src/routes/blocks.tsx
11
- var $$splitComponentImporter = () => import("./blocks-C1mgGTB3.js");
11
+ var $$splitComponentImporter = () => import("./blocks-DKy4yTF-.js");
12
12
  var Route = createFileRoute("/blocks")({
13
13
  component: lazyRouteComponent($$splitComponentImporter, "component"),
14
14
  validateSearch: validateBlocksSearch
@@ -1,9 +1,9 @@
1
- import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Jt as selectFieldClass, K as emptyStateClass, Mt as primaryButtonClass, Ot as pageTitleClass, Tt as pageHeaderClass, Wt as secondaryButtonClass, _t as mutedDotClass, a as blockRowClass, dn as textFieldClass, fn as textFieldShortClass, h as dangerButtonClass, i as blockRowBodyClass, m as cx, on as statusCopyClass, pn as timestampClass, q as errorCopyClass } from "./ui-qbmcMSSX.js";
1
+ import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, K as emptyStateClass, Mt as primaryButtonClass, Ot as pageTitleClass, Tt as pageHeaderClass, Wt as secondaryButtonClass, Yt as selectFieldClass, _t as mutedDotClass, a as blockRowClass, fn as textFieldClass, h as dangerButtonClass, i as blockRowBodyClass, m as cx, mn as timestampClass, pn as textFieldShortClass, q as errorCopyClass, sn as statusCopyClass } from "./ui-rDHeS-cc.js";
2
2
  import { _ as blockListResponseSchema, a as fetchQueryEnvelope, n as queryKeys, r as fetchJson, s as postAction } from "./query-client-BdauHBgd.js";
3
- import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-zUDAEmjL.js";
3
+ import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-DWag3IzT.js";
4
4
  import { t as validateBlocksSearch } from "./route-search-BUlQ5lGM.js";
5
5
  import { t as useDebouncedValue } from "./useDebouncedValue-DOnA6Xcy.js";
6
- import { t as Route } from "./blocks-DSgQghqP.js";
6
+ import { t as Route } from "./blocks-CaP_u3mY.js";
7
7
  import { useEffect, useMemo, useState } from "react";
8
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
  import { keepPreviousData, useQuery, useQueryClient } from "@tanstack/react-query";
@@ -1,4 +1,4 @@
1
- import { t as SavedTimelineView } from "./SavedTimelineView-BG1jnBp1.js";
1
+ import { t as SavedTimelineView } from "./SavedTimelineView-Bk9nfnb-.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  //#region src/routes/bookmarks.tsx?tsr-split=component
4
4
  function BookmarksRoute() {
@@ -1,7 +1,7 @@
1
- import { hn as tweetLinkClass, m as cx, vn as tweetMentionClass } from "./ui-qbmcMSSX.js";
2
- import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-zUDAEmjL.js";
3
- import { m as renderTweetPlainText, n as useFloatingPreview, r as useAvatarPreload, s as safeHttpUrl, t as ProfilePreview } from "./ProfilePreview-C6gAor_j.js";
4
- import { t as SmartTimestamp } from "./SmartTimestamp-DfwE1NGf.js";
1
+ import { gn as tweetLinkClass, m as cx, yn as tweetMentionClass } from "./ui-rDHeS-cc.js";
2
+ import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-DWag3IzT.js";
3
+ import { m as renderTweetPlainText, n as useFloatingPreview, r as useAvatarPreload, s as safeHttpUrl, t as ProfilePreview } from "./ProfilePreview-Bq-DSUM2.js";
4
+ import { t as SmartTimestamp } from "./SmartTimestamp-C06w_f9J.js";
5
5
  import { Fragment, useCallback, useEffect, useRef, useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { z } from "zod";
@@ -78,6 +78,66 @@ function getTweetUrl(tweet) {
78
78
  function getFallbackTweetUrl(tweetId) {
79
79
  return `https://x.com/i/status/${normalizeTweetReference(tweetId)}`;
80
80
  }
81
+ function comparableUrl(value) {
82
+ try {
83
+ const parsed = new URL(value);
84
+ return `${parsed.protocol}//${parsed.hostname}${parsed.pathname}`;
85
+ } catch {
86
+ return value.split("?")[0] ?? value;
87
+ }
88
+ }
89
+ function isOwnStatusMediaUrl(value, tweetId) {
90
+ try {
91
+ const parsed = new URL(value);
92
+ const host = parsed.hostname.replace(/^www\./, "");
93
+ if (host !== "x.com" && host !== "twitter.com") return false;
94
+ return new RegExp(`/status/${tweetId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/(?:photo|video)(?:/|$)`).test(parsed.pathname);
95
+ } catch {
96
+ return false;
97
+ }
98
+ }
99
+ function previewTextWithoutMediaLink(text, tweet, media) {
100
+ if (media.length === 0) return text;
101
+ const match = /(https?:\/\/[^\s]+)\s*$/.exec(text);
102
+ if (!match) return text;
103
+ const trailingUrl = match[1];
104
+ if (!trailingUrl) return text;
105
+ const mediaUrls = new Set(media.flatMap((item) => item.thumbnailUrl ? [item.url, item.thumbnailUrl] : [item.url]));
106
+ const comparableTrailing = comparableUrl(trailingUrl);
107
+ const directlyMatchesMedia = [...mediaUrls].some((url) => comparableUrl(url) === comparableTrailing);
108
+ const mediaEntityLostItsRange = (tweet.entities?.urls ?? []).some((entry) => {
109
+ if (entry.end > entry.start) return false;
110
+ return [...mediaUrls].some((url) => comparableUrl(url) === comparableUrl(entry.expandedUrl));
111
+ });
112
+ const isUnresolvedShortUrl = (() => {
113
+ try {
114
+ return new URL(trailingUrl).hostname.replace(/^www\./, "") === "t.co";
115
+ } catch {
116
+ return false;
117
+ }
118
+ })();
119
+ if (!directlyMatchesMedia && !isOwnStatusMediaUrl(trailingUrl, tweet.id) && !(isUnresolvedShortUrl && mediaEntityLostItsRange)) return text;
120
+ return text.slice(0, match.index).trimEnd();
121
+ }
122
+ function TweetPreviewMedia({ items }) {
123
+ const images = items.flatMap((item) => {
124
+ const url = item.type === "image" ? safeHttpUrl(item.thumbnailUrl ?? item.url) : safeHttpUrl(item.thumbnailUrl);
125
+ return url ? [{
126
+ item,
127
+ url
128
+ }] : [];
129
+ }).slice(0, 4);
130
+ if (images.length === 0) return null;
131
+ return /* @__PURE__ */ jsx("span", {
132
+ className: images.length === 1 ? "mt-2 block overflow-hidden rounded-xl border border-[var(--line)] bg-[var(--bg-active)]" : "mt-2 grid grid-cols-2 gap-1.5 overflow-hidden rounded-xl",
133
+ children: images.map(({ item, url }, index) => /* @__PURE__ */ jsx("img", {
134
+ alt: item.altText ?? `Tweet media ${String(index + 1)}`,
135
+ className: images.length === 1 ? "block max-h-64 w-full object-contain" : "block aspect-square size-full rounded-lg border border-[var(--line)] object-cover",
136
+ decoding: "async",
137
+ src: url
138
+ }, `${url}-${String(index)}`))
139
+ });
140
+ }
81
141
  function TweetSourceLink({ children, href, onClick, describedBy }) {
82
142
  return /* @__PURE__ */ jsx("a", {
83
143
  "aria-describedby": describedBy,
@@ -93,8 +153,9 @@ function TweetPreviewToken({ tweet, children }) {
93
153
  const preview = useFloatingPreview();
94
154
  useAvatarPreload(preview.referenceRef, tweet.authorProfile.id, tweet.authorProfile.avatarUrl);
95
155
  const article = tweet.entities?.article;
156
+ const media = tweet.media ?? [];
96
157
  const renderedText = renderTweetPlainText(tweet.text, tweet.entities ?? {});
97
- const previewText = article ? [article.title, article.previewText].filter((value, index, values) => Boolean(value) && values.indexOf(value) === index).join("\n\n") : renderedText;
158
+ const previewText = article ? [article.title, article.previewText].filter((value, index, values) => Boolean(value) && values.indexOf(value) === index).join("\n\n") : previewTextWithoutMediaLink(renderedText, tweet, media);
98
159
  return /* @__PURE__ */ jsxs("span", {
99
160
  ref: preview.referenceRef,
100
161
  className: "inline align-baseline",
@@ -143,9 +204,10 @@ function TweetPreviewToken({ tweet, children }) {
143
204
  })]
144
205
  }),
145
206
  /* @__PURE__ */ jsx("span", {
146
- className: "line-clamp-6 whitespace-pre-wrap [overflow-wrap:anywhere]",
207
+ className: "whitespace-pre-wrap [overflow-wrap:anywhere]",
147
208
  children: previewText
148
209
  }),
210
+ /* @__PURE__ */ jsx(TweetPreviewMedia, { items: media }),
149
211
  /* @__PURE__ */ jsxs("span", {
150
212
  className: "mt-2 flex gap-3 text-[12px] text-[var(--ink-soft)]",
151
213
  children: [
@@ -418,7 +480,8 @@ function profileAnalysisTweetToCitation(tweet, profile) {
418
480
  likeCount: tweet.likeCount,
419
481
  liked: false,
420
482
  bookmarked: false,
421
- needsReply: false
483
+ needsReply: false,
484
+ media: []
422
485
  };
423
486
  }
424
487
  function conversationTweetToCitation(tweet) {
@@ -436,7 +499,8 @@ function conversationTweetToCitation(tweet) {
436
499
  likeCount: tweet.likeCount,
437
500
  liked: false,
438
501
  bookmarked: false,
439
- needsReply: false
502
+ needsReply: false,
503
+ media: []
440
504
  };
441
505
  }
442
506
  function buildLookup(context) {
@@ -1,4 +1,4 @@
1
- import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ot as pageTitleClass, Tt as pageHeaderClass, Wt as secondaryButtonClass, m as cx, on as statusCopyClass, q as errorCopyClass, wt as pageHeaderActionsClass } from "./ui-qbmcMSSX.js";
1
+ import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ot as pageTitleClass, Tt as pageHeaderClass, Wt as secondaryButtonClass, m as cx, q as errorCopyClass, sn as statusCopyClass, wt as pageHeaderActionsClass } from "./ui-rDHeS-cc.js";
2
2
  import { S as liveDataSourcesResponseSchema, n as queryKeys, r as fetchJson } from "./query-client-BdauHBgd.js";
3
3
  import { useMemo } from "react";
4
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1,12 +1,12 @@
1
- import "./ui-qbmcMSSX.js";
2
- import "./client-stream-contracts-C2xbWVjm.js";
1
+ import "./ui-rDHeS-cc.js";
2
+ import "./client-stream-contracts-gtXEreFY.js";
3
3
  import { n as validateDiscussSearch } from "./route-search-BUlQ5lGM.js";
4
4
  import "react";
5
5
  import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
6
6
  import "react/jsx-runtime";
7
7
  import "lucide-react";
8
8
  //#region src/routes/discuss.tsx
9
- var $$splitComponentImporter = () => import("./discuss-QTo08NCN.js");
9
+ var $$splitComponentImporter = () => import("./discuss-CVGB4_I0.js");
10
10
  var Route$1 = createFileRoute("/discuss")({
11
11
  component: lazyRouteComponent($$splitComponentImporter, "component"),
12
12
  validateSearch: validateDiscussSearch
@@ -1,7 +1,7 @@
1
- import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ht as searchFieldInputClass, Jt as selectFieldClass, Mt as primaryButtonClass, Ot as pageTitleClass, Tt as pageHeaderClass, Ut as searchFieldShellClass, Vt as searchFieldIconClass, Wt as secondaryButtonClass, dn as textFieldClass, m as cx, q as errorCopyClass, wt as pageHeaderActionsClass } from "./ui-qbmcMSSX.js";
2
- import { a as useNdjsonRun, i as searchDiscussionStreamEventSchema, o as MarkdownViewer, t as isTerminalStreamEvent } from "./client-stream-contracts-C2xbWVjm.js";
1
+ import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ht as searchFieldInputClass, Mt as primaryButtonClass, Ot as pageTitleClass, Tt as pageHeaderClass, Ut as searchFieldShellClass, Vt as searchFieldIconClass, Wt as secondaryButtonClass, Yt as selectFieldClass, fn as textFieldClass, m as cx, q as errorCopyClass, wt as pageHeaderActionsClass } from "./ui-rDHeS-cc.js";
2
+ import { a as useNdjsonRun, i as searchDiscussionStreamEventSchema, o as MarkdownViewer, t as isTerminalStreamEvent } from "./client-stream-contracts-gtXEreFY.js";
3
3
  import { n as validateDiscussSearch } from "./route-search-BUlQ5lGM.js";
4
- import { t as Route$1 } from "./discuss-CJ1dau1j.js";
4
+ import { t as Route$1 } from "./discuss-BB8wFy4L.js";
5
5
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { CheckCircle2, ChevronDown, Loader2, RefreshCw, Search, Sparkles } from "lucide-react";