[feat] Show sessions and replay a transcript on mobile (6/12) - #5685
[feat] Show sessions and replay a transcript on mobile (6/12)#5685ardaerzin wants to merge 9 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR implements the mobile LITE flow. It adds project resolution, session search and pagination, read-only transcript replay, shared providers, workspace package integration, and container support. ChangesMobile LITE application
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant MobileApp
participant ContextResolver
participant ProjectsAPI
participant SessionsAPI
participant ChatScreen
participant loadSessionMessages
MobileApp->>ContextResolver: Resolve saved workspace and project context
ContextResolver->>ProjectsAPI: Fetch projects
ProjectsAPI-->>ContextResolver: Return project result
ContextResolver->>MobileApp: Redirect to project sessions route
MobileApp->>SessionsAPI: Query sessions with search and cursor
SessionsAPI-->>MobileApp: Return session pages
MobileApp->>ChatScreen: Open selected session
ChatScreen->>loadSessionMessages: Load transcript messages
loadSessionMessages-->>ChatScreen: Return transcript messages
ChatScreen-->>MobileApp: Render read-only transcript turns
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Trivy (0.72.0)Trivy execution failed: 2026-08-03T22:31:24Z FATAL Fatal error run error: fs scan error: scan error: scan failed: failed analysis: post analysis error: post analysis error: kubernetes scan error: fs filter error: fs filter error: walk error range error: stat web/mobile/doctor.config.json: no such file or directory: range error: stat web/mobile/doctor.config.json: no such file or directory Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 7
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 32e812e0-335c-45b6-bf48-d5eb695b3f19
⛔ Files ignored due to path filters (1)
web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (33)
.github/workflows/17-check-mobile.ymldocs/design/agenta-mobile/plans/2026-07-26-mobile-flows-lite.mdhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.dev.ymlweb/ee/docker/Dockerfile.devweb/mobile/docker/Dockerfile.ghweb/mobile/next.config.tsweb/mobile/package.jsonweb/mobile/src/features/app/AppProviders.tsxweb/mobile/src/features/app/ContextSync.tsxweb/mobile/src/features/chat/ChatHeader.tsxweb/mobile/src/features/chat/ChatScreen.tsxweb/mobile/src/features/chat/TurnRow.tsxweb/mobile/src/features/chat/states/ChatStates.tsxweb/mobile/src/features/chat/useSessionTranscript.tsweb/mobile/src/features/context/ContextResolver.tsxweb/mobile/src/features/context/WorkspaceProjectList.tsxweb/mobile/src/features/context/states/SignedOutNotice.tsxweb/mobile/src/features/sessions/SessionListScreen.tsxweb/mobile/src/features/sessions/SessionRow.tsxweb/mobile/src/features/sessions/SessionSearchBar.tsxweb/mobile/src/features/sessions/states/SessionListStates.tsxweb/mobile/src/features/sessions/useSessionsInfinite.tsweb/mobile/src/lib/context.tsweb/mobile/src/lib/env.tsweb/mobile/src/lib/queryClient.tsweb/mobile/src/pages/_app.tsxweb/mobile/src/pages/index.tsxweb/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/[session_id].tsxweb/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/index.tsxweb/oss/docker/Dockerfile.devweb/packages/agenta-sdk/src/resources.tsweb/turbo.json
| export const useSessionTranscript = (sessionId: string) => { | ||
| const [messages, setMessages] = useState<UIMessage[]>([]) | ||
| const [state, setState] = useState<"loading" | "ready" | "empty">("loading") | ||
| useEffect(() => { | ||
| let cancelled = false | ||
| let refreshed = false | ||
| setState("loading") | ||
| setMessages([]) | ||
| void loadSessionMessages(sessionId, (fresh) => { | ||
| // Disk-restore revalidation re-delivery — fresh is non-empty by contract. | ||
| if (cancelled) return | ||
| refreshed = true | ||
| setMessages(fresh) | ||
| setState("ready") | ||
| }).then((msgs) => { | ||
| // A fast revalidation can beat this one-shot resolve; never clobber it. | ||
| if (cancelled || refreshed) return | ||
| setMessages(msgs ?? []) | ||
| setState(msgs && msgs.length > 0 ? "ready" : "empty") | ||
| }) | ||
| return () => { | ||
| cancelled = true | ||
| } | ||
| }, [sessionId]) | ||
| return {messages, state} | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Use TanStack Query instead of manual useEffect fetching.
This hook fetches data with useEffect and manual useState tracking. Wrap loadSessionMessages in a useQuery/atomWithQuery call instead, and use the refresh callback to update the query cache (for example through queryClient.setQueryData). This restores native loading/error/retry semantics and keeps the hook consistent with the rest of the codebase.
As per coding guidelines: "Use atomWithQuery with TanStack Query for API data fetching ... Do not use useEffect with manual fetching or introduce SWR+axios for new features."
Source: Coding guidelines
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Add error handling to the transcript load.
loadSessionMessages(...).then(...) has no .catch(). If the promise rejects, state stays "loading" indefinitely, and the rejection goes unhandled. The user sees an infinite spinner with no retry option on a transient failure.
Add an "error" state and a .catch() handler, and surface a retry action from ChatScreen.
🐛 Proposed fix
- const [state, setState] = useState<"loading" | "ready" | "empty">("loading")
+ const [state, setState] = useState<"loading" | "ready" | "empty" | "error">("loading")
useEffect(() => {
let cancelled = false
let refreshed = false
setState("loading")
setMessages([])
void loadSessionMessages(sessionId, (fresh) => {
if (cancelled) return
refreshed = true
setMessages(fresh)
setState("ready")
}).then((msgs) => {
if (cancelled || refreshed) return
setMessages(msgs ?? [])
setState(msgs && msgs.length > 0 ? "ready" : "empty")
- })
+ }).catch(() => {
+ if (cancelled || refreshed) return
+ setState("error")
+ })
return () => {
cancelled = true
}
}, [sessionId])| const query = useQuery({ | ||
| queryKey: ["mobile", "projects"], | ||
| queryFn: () => fetchProjects(), | ||
| enabled: !stored, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Validate persisted context before redirecting.
A stored pair disables fetchProjects() and becomes target without checking that the user can still access the workspace and project. If the project was deleted or access was removed, /m/ keeps redirecting to the stale route and cannot show the picker or signed-out state.
Fetch projects for stored contexts. Redirect only when the stored pair exists in the validated result. Otherwise, clear the stored context and continue with normal project selection.
Also applies to: 46-62
| const query = useQuery({ | ||
| queryKey: ["mobile", "projects"], | ||
| queryFn: () => fetchProjects(), | ||
| enabled: !stored, | ||
| staleTime: 30_000, | ||
| }) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 3 '\batomWithQuery\b|\buseQuery\b' web/mobileRepository: Agenta-AI/agenta
Length of output: 2315
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Tracked mobile files containing atomWithQuery:\n'
git ls-files 'web/mobile/**' | xargs rg -l 'atomWithQuery' || true
printf '\nContextResolver excerpt:\n'
sed -n '1,80p' web/mobile/src/features/context/ContextResolver.tsx | cat -n
printf '\nMobile package deps query/jotai availability:\n'
if [ -f web/mobile/package.json ]; then
jq '{dependencies, devDependencies}' web/mobile/package.json
fi
printf '\nProject query/atom definitions referencing projects or mobile projects anywhere:\n'
rg -n 'fetchProjects|mobile.*projects|atomWithQuery|atomWithStorage' web/packages web/mobile || trueRepository: Agenta-AI/agenta
Length of output: 27472
Move project fetching into an atomWithQuery.
ContextResolver.tsx uses @tanstack/react-query's useQuery instead of the mobile data-layer pattern. Keep fetchProjects wrapped in a Jotai query atom, consume it with Jotai, and remove the direct useQuery import.
Source: Coding guidelines
| <button | ||
| key={project.project_id} | ||
| type="button" | ||
| className="border-border rounded-md border px-3 py-2.5 text-left text-xs" | ||
| onClick={() => | ||
| void router.replace( | ||
| `/w/${group.workspaceId}/p/${project.project_id}/sessions`, | ||
| ) | ||
| } | ||
| > | ||
| {project.project_name} | ||
| {project.is_demo ? ( | ||
| <span className="text-muted-foreground ml-2">demo</span> | ||
| ) : null} | ||
| </button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Add explicit interaction states to the new buttons.
The new controls define static semantic colors but no hover, active, or visible keyboard-focus state. Add token-based interaction classes for both controls.
web/mobile/src/features/context/WorkspaceProjectList.tsx#L21-L35: Add hover, active, andfocus-visiblestyles to each project button.web/mobile/src/features/context/ContextResolver.tsx#L82-L88: Add the same interaction states to the Retry button.
As per coding guidelines, implement light and dark appearance and interaction states for every added or changed UI element.
📍 Affects 2 files
web/mobile/src/features/context/WorkspaceProjectList.tsx#L21-L35(this comment)web/mobile/src/features/context/ContextResolver.tsx#L82-L88
Source: Coding guidelines
45fa66f to
5243f24
Compare
b43b6c7 to
42873d9
Compare
5243f24 to
7b97468
Compare
42873d9 to
83782a0
Compare
7b97468 to
2ac567c
Compare
83782a0 to
4822eb6
Compare
2ac567c to
e9e9e65
Compare
4822eb6 to
7a90b8c
Compare
|
Verified these against the code. None are shipped defects, and two rest on a premise that does not hold for this app — so I would rather argue them than change the architecture quietly.
Validate persisted context before redirecting — real, but not a silent trap, and not free. A stored pair pointing at a deleted project does forward into a dead route. Validating first would defeat the point of the fast path, which exists to skip a round trip on every launch. There is now a way out that did not exist when this was written: the sessions header carries a project switcher, and Distinguish first-page from later-page failure — fair, deferred. Today any null page marks the list failed. In practice the first page is what fails (auth, project scope); a later page failing mid-scroll is rarer and the retry affordance still works. Worth splitting, not urgent. Explicit interaction states on the picker buttons — superseded. That component was replaced further up the stack: the workspace selector moved into the pinned header and the list became Use the shared API-boundary validator in |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
.github/workflows/17-check-mobile.yml (4)
22-25: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftSerialize publication by the image tag.
Workflow concurrency separates runs by pull request or ref, but manual runs on different refs can still choose the same
image_tagand push to${TAG}-amd64/${TAG}-arm64. Themerge-manifestsjob then creates${TAG}from whichever per-arch images GHCR returns. Add a publish-specific concurrency group keyed to the final tag, usecancel-in-progress: falsefor the manifest step, or reject reusing an existing tag before publishing.
109-112: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winLimit
packages: writeto the publish job.
build-imageruns onpull_request, and GHCR push/cache writes are conditional onneeds.prepare.outputs.push == 'true'. Keep this job read-only instead of granting write permissions up front. Use a separate job withpackages: writefor the registry publish path only.
82-108: 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick winTreat workflow outputs as untrusted data.
image_tagis written unescaped to$GITHUB_OUTPUTunderprepare.outputs, and laterworkflow_dispatchsteps interpolateneeds.prepare.outputs.image_tagandneeds.prepare.outputs.pushdirectly intorun:Bash. Validate the tag before setting job outputs, then passIMAGEandPUSHthroughenv:, quoting any step output values before shell expansion.Source: Linters/SAST tools
45-45: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDisable checkout credential persistence.
actions/checkout@v6persists credentials by default in this checkout job. The subsequentpnpm install --frozen-lockfilestep can read those credentials through repository-controlled lifecycle scripts. Addpersist-credentials: falseto the checkout steps at lines 45, 74, and 130.Source: Linters/SAST tools
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e7574674-71f2-48b1-a4ef-8c55dd063286
⛔ Files ignored due to path filters (1)
web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (33)
.github/workflows/17-check-mobile.ymldocs/design/agenta-mobile/plans/2026-07-26-mobile-flows-lite.mdhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.dev.ymlweb/ee/docker/Dockerfile.devweb/mobile/docker/Dockerfile.ghweb/mobile/next.config.tsweb/mobile/package.jsonweb/mobile/src/features/app/AppProviders.tsxweb/mobile/src/features/app/ContextSync.tsxweb/mobile/src/features/chat/ChatHeader.tsxweb/mobile/src/features/chat/ChatScreen.tsxweb/mobile/src/features/chat/TurnRow.tsxweb/mobile/src/features/chat/states/ChatStates.tsxweb/mobile/src/features/chat/useSessionTranscript.tsweb/mobile/src/features/context/ContextResolver.tsxweb/mobile/src/features/context/WorkspaceProjectList.tsxweb/mobile/src/features/context/states/SignedOutNotice.tsxweb/mobile/src/features/sessions/SessionListScreen.tsxweb/mobile/src/features/sessions/SessionRow.tsxweb/mobile/src/features/sessions/SessionSearchBar.tsxweb/mobile/src/features/sessions/states/SessionListStates.tsxweb/mobile/src/features/sessions/useSessionsInfinite.tsweb/mobile/src/lib/context.tsweb/mobile/src/lib/env.tsweb/mobile/src/lib/queryClient.tsweb/mobile/src/pages/_app.tsxweb/mobile/src/pages/index.tsxweb/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/[session_id].tsxweb/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/index.tsxweb/oss/docker/Dockerfile.devweb/packages/agenta-sdk/src/resources.tsweb/turbo.json
🚧 Files skipped from review as they are similar to previous changes (32)
- hosting/docker-compose/oss/docker-compose.dev.yml
- web/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/index.tsx
- web/mobile/src/features/context/states/SignedOutNotice.tsx
- web/oss/docker/Dockerfile.dev
- web/mobile/src/features/chat/useSessionTranscript.ts
- hosting/docker-compose/ee/docker-compose.dev.yml
- web/mobile/src/features/chat/ChatHeader.tsx
- web/mobile/src/lib/env.ts
- web/ee/docker/Dockerfile.dev
- web/mobile/src/features/sessions/SessionSearchBar.tsx
- web/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/[session_id].tsx
- web/mobile/src/lib/queryClient.ts
- web/turbo.json
- web/mobile/src/features/context/WorkspaceProjectList.tsx
- web/mobile/src/features/app/ContextSync.tsx
- web/mobile/src/pages/index.tsx
- web/mobile/src/features/sessions/useSessionsInfinite.ts
- web/mobile/src/features/chat/states/ChatStates.tsx
- web/mobile/src/features/sessions/SessionListScreen.tsx
- web/mobile/src/pages/_app.tsx
- web/mobile/src/features/sessions/states/SessionListStates.tsx
- web/mobile/src/features/app/AppProviders.tsx
- web/mobile/next.config.ts
- web/mobile/src/features/chat/TurnRow.tsx
- web/mobile/src/features/context/ContextResolver.tsx
- web/mobile/src/features/sessions/SessionRow.tsx
- web/mobile/docker/Dockerfile.gh
- web/mobile/package.json
- web/mobile/src/features/chat/ChatScreen.tsx
- web/mobile/src/lib/context.ts
- web/packages/agenta-sdk/src/resources.ts
- docs/design/agenta-mobile/plans/2026-07-26-mobile-flows-lite.md
e9e9e65 to
89fe72f
Compare
7a90b8c to
2a51cb5
Compare
89fe72f to
bfad8e0
Compare
2a51cb5 to
e55669f
Compare
…ontainers
Both dev composes mount web/packages into web-mobile (same line the web
service already has); both dev Dockerfiles now COPY the agenta-chat
manifest and source (they predate the package); Dockerfile.gh copies the
@agenta/* workspace closure (shared, ui, entities, playground, chat, sdk,
api-client full-dir for its prepare build) so pnpm install resolves the
new workspace deps.
Operator runbook (do not run in-session): the live web-mobile container
has neither the new deps nor @agenta/chat. Applying this change requires
a dev web image rebuild + web-mobile recreate:
run.sh --ee --dev --with-mobile --build
Interim bootstrap of the RUNNING container, if needed before the rebuild:
docker exec agenta-ee-dev-web-mobile-1 ls /app/packages # confirm what's baked
docker cp web/packages/agenta-chat agenta-ee-dev-web-mobile-1:/app/packages/
docker cp web/mobile/package.json agenta-ee-dev-web-mobile-1:/app/mobile/package.json
docker cp web/pnpm-lock.yaml agenta-ee-dev-web-mobile-1:/app/pnpm-lock.yaml
docker exec agenta-ee-dev-web-mobile-1 pnpm install
docker restart agenta-ee-dev-web-mobile-1
Any null page marked the whole session list failed, so a page that failed halfway down a long scroll replaced every row already on screen with the full-screen error. Only the first page failing leaves nothing to show; a later one should keep the rows and offer the retry where the scroll stopped, which is what the load-more affordance now says when it happens. The classification moved into `classifyPageFailure` beside the list's other pure helpers, so the package unit suite covers it rather than only a rendered screen. Also drops the stored workspace/project pair when its project will not load. That pair is the fast path `/m/` uses to skip the picker, and a deleted project turned it into a loop: every launch forwarded straight back to a list that could not render, with no way out but the switcher. Clearing it is safe to over-do, since ContextSync rewrites it from the next project that loads. Project fetching now validates through `safeParseWithLogging` from `@agenta/entities/shared`, the repo's API-boundary validator, instead of an inline safeParse with its own console.error.
bfad8e0 to
29f6858
Compare
e55669f to
e9ce407
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
.github/workflows/17-check-mobile.yml (5)
208-213: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winCheck effective UID instead of exact
Config.Userstrings.Docker
USERsupportsuser:groupanduid:gidforms, soroot:rootand0:0will pass["$USER" = "root"]/["$USER" = "0"]and reportPASS. Reject root UID forms such as""|root|0|root:*|0:*, or rundocker execand checkid -u.
45-45: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDisable checkout credential persistence in each checkout step.
These checkout steps use
actions/checkout’s persisted credentials, which make the runner’s Git credentials available to later PR-controlled commands such aspnpm installand build steps. Setpersist-credentials: falsefor the checkout steps at lines 45, 74, and 144.Suggested change
- - uses: actions/checkout@v6 + - uses: actions/checkout@v6 + with: + persist-credentials: falseSource: Linters/SAST tools
124-126: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winKeep
build-imageread-only for pull requests.
build-imageuses PR-controlled code withpermissions: packages: write. Same-repository pull requests can provide write-capableGITHUB_TOKENvalues depending on repository settings, while cross-repository pull requests are still subject to admin-controlled token access. Use a trusted, post-merge workflow, orworkflow_dispatch, for GHCR publishing and keep the PR build job read-only.
105-117: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winCap the base tag length before appending the architecture suffix.
Line 114 accepts
image_tagup to 128 characters, but the build ref appends-${{ matrix.arch }}(-amd64or-arm64), and the manual Docker load/tag step does the same. Tags of 123–128 characters become 129–134 characters, which exceeds the OCI reference tag length limit. Limit the base tag to 122 characters, or validate each derivedimage_tag-${{ matrix.arch }}tag.Suggested change
- if [ "${`#TAG`}" -gt 128 ]; then - echo "::error::image_tag is longer than 128 characters" + MAX_BASE_TAG_LENGTH=122 + if [ "${`#TAG`}" -gt "$MAX_BASE_TAG_LENGTH" ]; then + echo "::error::image_tag is too long for the architecture tags" exit 1 fi
35-37: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winKey manual image publishing by the requested image tag.
workflow_dispatchacceptsimage_tag, but the workflow’s concurrency group usesgithub.ref_name. Manual runs from different refs can build and merge the sameTAG-amd64andTAG-arm64images concurrently, producing a manifest that mixes arch builds from different runs. Key the tag group withinputs.image_tagand disable canceling manual publishes, or queue them for the same tag.Suggested change
- group: check-mobile-${{ github.event.pull_request.number || github.ref_name }} - cancel-in-progress: true + group: check-mobile-${{ github.event.pull_request.number || inputs.image_tag || github.sha }} + cancel-in-progress: ${{ github.event_name != 'workflow_dispatch' }}
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b45adcef-1ced-427b-9990-2296091db215
⛔ Files ignored due to path filters (1)
web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (35)
.github/workflows/17-check-mobile.ymldocs/design/agenta-mobile/plans/2026-07-26-mobile-flows-lite.mdhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.dev.ymlweb/ee/docker/Dockerfile.devweb/mobile/docker/Dockerfile.ghweb/mobile/next.config.tsweb/mobile/package.jsonweb/mobile/src/features/app/AppProviders.tsxweb/mobile/src/features/app/ContextSync.tsxweb/mobile/src/features/chat/ChatHeader.tsxweb/mobile/src/features/chat/ChatScreen.tsxweb/mobile/src/features/chat/TurnRow.tsxweb/mobile/src/features/chat/states/ChatStates.tsxweb/mobile/src/features/chat/useSessionTranscript.tsweb/mobile/src/features/context/ContextResolver.tsxweb/mobile/src/features/context/WorkspaceProjectList.tsxweb/mobile/src/features/context/states/SignedOutNotice.tsxweb/mobile/src/features/sessions/SessionListScreen.tsxweb/mobile/src/features/sessions/SessionRow.tsxweb/mobile/src/features/sessions/SessionSearchBar.tsxweb/mobile/src/features/sessions/pageFailure.tsweb/mobile/src/features/sessions/states/SessionListStates.tsxweb/mobile/src/features/sessions/useSessionsInfinite.tsweb/mobile/src/lib/context.tsweb/mobile/src/lib/env.tsweb/mobile/src/lib/queryClient.tsweb/mobile/src/pages/_app.tsxweb/mobile/src/pages/index.tsxweb/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/[session_id].tsxweb/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/index.tsxweb/mobile/tests/unit/pageFailure.test.tsweb/oss/docker/Dockerfile.devweb/packages/agenta-sdk/src/resources.tsweb/turbo.json
🚧 Files skipped from review as they are similar to previous changes (31)
- web/turbo.json
- hosting/docker-compose/ee/docker-compose.dev.yml
- web/ee/docker/Dockerfile.dev
- web/mobile/src/lib/queryClient.ts
- web/oss/docker/Dockerfile.dev
- web/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/index.tsx
- hosting/docker-compose/oss/docker-compose.dev.yml
- web/mobile/src/features/chat/useSessionTranscript.ts
- web/mobile/src/features/sessions/SessionRow.tsx
- web/mobile/package.json
- web/mobile/src/features/app/ContextSync.tsx
- web/mobile/src/pages/index.tsx
- web/mobile/src/features/sessions/SessionSearchBar.tsx
- web/mobile/src/features/chat/ChatScreen.tsx
- web/mobile/src/features/chat/states/ChatStates.tsx
- web/mobile/src/features/context/states/SignedOutNotice.tsx
- web/mobile/src/features/chat/TurnRow.tsx
- web/mobile/src/pages/w/[workspace_id]/p/[project_id]/sessions/[session_id].tsx
- web/mobile/src/features/app/AppProviders.tsx
- web/mobile/next.config.ts
- web/mobile/src/features/sessions/useSessionsInfinite.ts
- web/packages/agenta-sdk/src/resources.ts
- web/mobile/src/features/context/WorkspaceProjectList.tsx
- docs/design/agenta-mobile/plans/2026-07-26-mobile-flows-lite.md
- web/mobile/src/pages/_app.tsx
- web/mobile/src/lib/context.ts
- web/mobile/src/features/sessions/states/SessionListStates.tsx
- web/mobile/src/lib/env.ts
- web/mobile/src/features/context/ContextResolver.tsx
- web/mobile/docker/Dockerfile.gh
- web/mobile/src/features/chat/ChatHeader.tsx
Context
Lane 1 gave
/ma shell. This lane makes it show something real: your sessions, and a read-only transcript of one.Changes
The
@agenta/*packages are wired into the mobile app (and mounted/baked into its containers), with providers, SDK host pinning, and route-scoped project state. The root resolves your workspace and project: it forwards straight to the last one you used, and otherwise shows a picker.The sessions list is server-searched and cursor-paged on the ordering lane 2 added, with archived rows filtered server-side (an all-archived first page would otherwise render "No sessions." while live rows sat behind the cursor). Opening a session replays its transcript through the durable record log, read-only.
Tests / notes
@agenta/entities; the app-layer import ban is lint-enforced, so nothing reaches intoweb/oss.What to QA
/msigned in. You land on your last project's session list, or a picker if there is no last one.