diff --git a/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.test.tsx b/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.test.tsx index 4ebbd9d8a99c0..e774f398bfa6b 100644 --- a/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.test.tsx +++ b/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.test.tsx @@ -110,14 +110,25 @@ const ref = { digest: "a".repeat(64), }; vi.mock("../../state/query", () => ({ - useEnvironmentQuery: (request: ExternalHistoryRequest) => { + useEnvironmentQuery: (request: ExternalHistoryRequest | null) => { + if (request === null) + return { data: null, error: null, isPending: false, isSuccess: false, refresh: vi.fn() }; state.requests.push(request); const data: ExternalHistoryResponse = request.operation === "sources" ? { operation: "sources", enabled: true, - sources: [{ id: "codex-history", label: "Native Codex", kind: "codex" }], + sources: [ + { + id: "codex-history", + label: "Native Codex", + kind: "codex", + capabilities: { cwdFilter: true, archived: true }, + status: "ready", + }, + ], + unsupported: [], } : request.operation === "search" ? { @@ -148,7 +159,7 @@ vi.mock("../../state/query", () => ({ totalChars: 33, nextTextOffset: request.textOffset ? null : 16, }; - return { data, error: null, isPending: false, refresh: vi.fn() }; + return { data, error: null, isPending: false, isSuccess: true, refresh: vi.fn() }; }, })); @@ -158,7 +169,7 @@ const configFor = (supported: boolean, enabled = true) => ({ environment: { capabilities: supported ? { externalHistory: 1 as const } : {} }, settings: { ...DEFAULT_SERVER_SETTINGS, - externalHistory: { enabled, chatGptExportPaths: ["/remote/export.json"] }, + externalHistory: { enabled }, }, }); @@ -200,9 +211,6 @@ it("keeps remote history read-only without settings permission and stops reads w expect(container.textContent).toContain("Update this server"); act(() => registry.set(config, configFor(true))); expect(button("Allow external history search").disabled).toBe(true); - expect( - container.querySelector('[aria-label="ChatGPT export paths"]')?.disabled, - ).toBe(true); const input = container.querySelector( '[aria-label="Search external history"]', )!; @@ -212,8 +220,6 @@ it("keeps remote history read-only without settings permission and stops reads w }); await click("This project"); await click("Search"); - expect(container.textContent).toContain("No matches on this page. Continue"); - await click("Continue search"); expect(container.textContent).toContain("Compiler investigation"); expect(state.requests).toContainEqual({ operation: "search", @@ -229,7 +235,7 @@ it("keeps remote history read-only without settings permission and stops reads w expect(container.textContent).toContain("Second exact page"); expect(container.textContent).not.toContain("First exact page"); await click("Search"); - expect(container.textContent).toContain("No matches on this page. Continue"); + expect(container.textContent).toContain("Compiler investigation"); expect(container.textContent).not.toContain("Second exact page"); expect(state.update).not.toHaveBeenCalled(); act(() => registry.set(config, configFor(true, false))); diff --git a/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.tsx b/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.tsx index eb23d85ad52fc..f4d24078a91e6 100644 --- a/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.tsx +++ b/apps/mobile/src/features/external-history/ExternalHistoryRouteScreen.tsx @@ -1,16 +1,23 @@ import { useAtomValue } from "@effect/atom-react"; import { useIsFocused, useNavigation, type StaticScreenProps } from "@react-navigation/native"; -import { externalHistoryRangeLabel } from "@t3tools/client-runtime/externalHistory"; +import { + externalHistoryPagingReducer, + initialExternalHistoryPaging, + externalHistoryRangeLabel, + externalHistorySearchFilters, + externalHistorySourceStatusLabel, +} from "@t3tools/client-runtime/externalHistory"; import { squashAtomCommandFailure } from "@t3tools/client-runtime/state/runtime"; import { EnvironmentId, type ExternalHistoryMatch, type ExternalHistoryRequest, type ExternalHistorySettings, + type ExternalHistorySource, type ProjectId, } from "@t3tools/contracts"; -import { useState } from "react"; -import { ScrollView, View } from "react-native"; +import { useEffect, useReducer, useState, type ReactNode } from "react"; +import { Platform, ScrollView, View } from "react-native"; import { AppBar } from "../../components/ui/AppBar"; import { AppText as Text, AppTextInput } from "../../components/ui/AppText"; @@ -67,33 +74,34 @@ export function ExternalHistoryRouteScreen( - Search Codex conversations and configured ChatGPT exports on this environment. Open - the original evidence behind each match. + Search agent conversations found on this environment. Open the original evidence + behind each match. - {config.settings.externalHistory.enabled ? ( - - ) : ( - - External history search is off for this environment. - - )} + > + {config.settings.externalHistory.enabled ? ( + + ) : ( + + External history search is off for this environment. + + )} + ) : !supported ? ( @@ -108,12 +116,12 @@ export function ExternalHistoryRouteScreen( function HistorySettings(props: { readonly environmentId: EnvironmentId; readonly settings: ExternalHistorySettings; + readonly children: ReactNode; }) { const canWrite = useAtomValue( serverEnvironment.updateSettings.permissionAtom(props.environmentId), ); const update = useAtomCommand(serverEnvironment.updateSettings, { reportFailure: false }); - const [paths, setPaths] = useState(props.settings.chatGptExportPaths.join("\n")); const [pending, setPending] = useState(false); const [error, setError] = useState(null); const save = async (settings: ExternalHistorySettings) => { @@ -128,68 +136,40 @@ function HistorySettings(props: { if (result._tag === "Failure") setError(String(squashAtomCommandFailure(result))); }; return ( - - void save({ ...props.settings, enabled })} - /> - - Makes these sources available to this environment's connected clients and agents with thread - access. Source files stay in their existing locations. - - ChatGPT export paths - - - Paths refer to files on the T3 server. Remove a path to stop offering that export. - -