fix(app): show actionable chat search failures

Keep transport error details in the search model while showing localized retry guidance. Use named client request options for timeline search.
This commit is contained in:
Mohamed Boudra
2026-09-12 12:20:52 +02:00
parent 2bb62bb8e4
commit 75ed573f11
12 changed files with 32 additions and 7 deletions
@@ -163,6 +163,11 @@ test("shows a disconnected search failure and recovers with Retry", async ({ pag
await expectReconnectingToastVisible(page);
await searchChat(page, "hello world");
await expect(status(page)).toHaveText("Failed");
await expect(
page.getByText("Could not search this chat. Check the host connection and retry.", {
exact: true,
}),
).toBeVisible();
await expect(page.getByRole("button", { name: "Retry", exact: true })).toBeVisible();
gate.restore();
await expectReconnectingToastGone(page);
@@ -62,7 +62,7 @@ export function ChatFind({
search(query, cursor) {
const client = getHostRuntimeStore().getClient(serverId);
if (!client) return Promise.reject(new Error("Host disconnected"));
return client.searchAgentTimeline(agentId, query, cursor);
return client.searchAgentTimeline({ agentId, query, cursor });
},
load(targetEpoch, seq) {
return getHostRuntimeStore().fetchAgentTimeline(
@@ -136,7 +136,7 @@ export function ChatFind({
/>
{state.error && (
<View style={styles.error}>
<Text style={styles.errorText}>{state.error}</Text>
<Text style={styles.errorText}>{t("paneFind.searchFailed")}</Text>
<Button size="xs" variant="ghost" onPress={model.retry}>
{t("paneFind.retry")}
</Button>
+1
View File
@@ -3,6 +3,7 @@ import { pluginSettings } from "./plugin-settings";
export const ar: TranslationResources = {
paneFind: {
searchFailed: "تعذر البحث في هذه المحادثة. تحقق من الاتصال بالمضيف وأعد المحاولة.",
searching: "جارٍ البحث…",
loading: "جارٍ التحميل…",
failed: "فشل",
+1
View File
@@ -1,5 +1,6 @@
export const en = {
paneFind: {
searchFailed: "Could not search this chat. Check the host connection and retry.",
searching: "Searching…",
loading: "Loading…",
failed: "Failed",
+2
View File
@@ -3,6 +3,8 @@ import { pluginSettings } from "./plugin-settings";
export const es: TranslationResources = {
paneFind: {
searchFailed:
"No se pudo buscar en este chat. Comprueba la conexión con el host y vuelve a intentarlo.",
searching: "Buscando…",
loading: "Cargando…",
failed: "Error",
+2
View File
@@ -3,6 +3,8 @@ import { pluginSettings } from "./plugin-settings";
export const fr: TranslationResources = {
paneFind: {
searchFailed:
"Impossible de rechercher dans cette conversation. Vérifiez la connexion à l’hôte et réessayez.",
searching: "Recherche…",
loading: "Chargement…",
failed: "Échec",
+2
View File
@@ -3,6 +3,8 @@ import { pluginSettings } from "./plugin-settings";
export const ja: TranslationResources = {
paneFind: {
searchFailed:
"このチャットを検索できませんでした。ホストへの接続を確認して再試行してください。",
searching: "検索中…",
loading: "読み込み中…",
failed: "失敗",
+1
View File
@@ -3,6 +3,7 @@ import { pluginSettings } from "./plugin-settings";
export const ko: TranslationResources = {
paneFind: {
searchFailed: "이 채팅을 검색할 수 없습니다. 호스트 연결을 확인하고 다시 시도하세요.",
searching: "검색 중…",
loading: "불러오는 중…",
failed: "실패",
+2
View File
@@ -3,6 +3,8 @@ import { pluginSettings } from "./plugin-settings";
export const ptBR: TranslationResources = {
paneFind: {
searchFailed:
"Não foi possível pesquisar nesta conversa. Verifique a conexão com o host e tente novamente.",
searching: "Buscando…",
loading: "Carregando…",
failed: "Falhou",
+2
View File
@@ -3,6 +3,8 @@ import { pluginSettings } from "./plugin-settings";
export const ru: TranslationResources = {
paneFind: {
searchFailed:
"Не удалось выполнить поиск в чате. Проверьте подключение к хосту и повторите попытку.",
searching: "Поиск…",
loading: "Загрузка…",
failed: "Ошибка",
+1
View File
@@ -3,6 +3,7 @@ import { pluginSettings } from "./plugin-settings";
export const zhCN: TranslationResources = {
paneFind: {
searchFailed: "无法搜索此聊天。请检查主机连接后重试。",
searching: "搜索中…",
loading: "加载中…",
failed: "失败",
+11 -5
View File
@@ -576,6 +576,12 @@ export interface FetchAgentTimelineOptions {
timeout?: number;
}
export interface AgentTimelineSearchOptions {
agentId: string;
query: string;
cursor?: number;
}
export type AgentTimelineSearchPayload = Extract<
SessionOutboundMessage,
{ type: "agent.timeline.search.response" }
@@ -2973,11 +2979,11 @@ export class DaemonClient {
return { seq: payload.seq, epoch: payload.epoch };
}
async searchAgentTimeline(
agentId: string,
query: string,
cursor?: number,
): Promise<AgentTimelineSearchPayload> {
async searchAgentTimeline({
agentId,
query,
cursor,
}: AgentTimelineSearchOptions): Promise<AgentTimelineSearchPayload> {
const requestId = this.createRequestId();
const payload = await this.sendCorrelatedSessionRequest({
requestId,