diff --git a/.kilo_workflow/learnings/mobile-remote-cli-model-id-prefix.md b/.kilo_workflow/learnings/mobile-remote-cli-model-id-prefix.md new file mode 100644 index 00000000000..91482b6df59 --- /dev/null +++ b/.kilo_workflow/learnings/mobile-remote-cli-model-id-prefix.md @@ -0,0 +1,18 @@ +# mobile: remote-cli.sh exec run -m kilo-auto/efficient fails ProviderModelNotFoundError — CLI ids need the kilo/ prefix + +Symptom: `apps/mobile/e2e/remote-cli.sh exec run -m kilo-auto/efficient --auto ""` fails +with `ProviderModelNotFoundError` / `Model not found: kilo-auto/efficient`, and the run still +creates an empty session row in the mobile Agents list. + +Cause: the handoff/workflow "kilo-auto/efficient" id is the IN-APP id. The CLI's provider/model +format needs the provider prefix: `kilo/kilo-auto/efficient` (WORKFLOW.md's "kilo/kilo-auto/* are +the same models as CLI ids" is the only place this is stated, and it is easy to read past). + +Fix: run `apps/mobile/e2e/remote-cli.sh exec models` first and copy the exact id +(`kilo/kilo-auto/efficient`); never guess from the in-app id. Side effect to expect: each failed +run leaves an empty `New session - ` row in the session list — harmless, but do not confuse +it with the content session when picking rows to tap. + +Bonus: a fresh E2E account starts with $0 credit; `kilo/kilo-auto/efficient` then fails with +"Add credits to continue". Seed first: +`pnpm dev:seed app:user-id ` then `pnpm dev:seed app:add-credits 10`. diff --git a/apps/mobile/src/app/(app)/agent-chat/[session-id].tsx b/apps/mobile/src/app/(app)/agent-chat/[session-id].tsx index 0c41a3335e8..d802f2e3834 100644 --- a/apps/mobile/src/app/(app)/agent-chat/[session-id].tsx +++ b/apps/mobile/src/app/(app)/agent-chat/[session-id].tsx @@ -88,6 +88,7 @@ export default function SessionDetailScreen() { info={undefined} totalCostMicrodollars={null} hasMessages={false} + loading /> } /> diff --git a/apps/mobile/src/components/agents/session-context-metrics.tsx b/apps/mobile/src/components/agents/session-context-metrics.tsx index aee6ec7f397..1b43a9d83b7 100644 --- a/apps/mobile/src/components/agents/session-context-metrics.tsx +++ b/apps/mobile/src/components/agents/session-context-metrics.tsx @@ -16,6 +16,11 @@ type SessionContextMetricsProps = { totalCostMicrodollars: number | null; hasMessages: boolean; onPress?: () => void; + /** + * Hide the pill while the session page loads; the layout box stays reserved so the header does not + * shift. + */ + loading?: boolean; }; const RING_SIZE = 28; @@ -37,11 +42,12 @@ export function SessionContextMetrics({ totalCostMicrodollars, hasMessages, onPress, + loading = false, }: Readonly) { const content = getHeaderPillContent({ info, totalCostMicrodollars, hasMessages }); // Single source for element kind and a11y affordance wording so a future // caller with interactive content but no onPress cannot advertise a tap. - const pressable = content.interactive && onPress != null; + const pressable = !loading && content.interactive && onPress != null; const accessibilityLabel = getMetricsAccessibilityLabel({ info, totalCostMicrodollars, @@ -52,20 +58,16 @@ export function SessionContextMetrics({ // NativeWind 5 preview (rem ≈ 14px here), so an arbitrary px value is required // for the 44pt minimum touch target; height is identical in every pill state. const pillClassName = - 'h-[44px] flex-row items-center gap-1.5 rounded-full border border-border bg-secondary px-2.5'; + 'h-[44px] flex-row items-center gap-2 rounded-full border border-border bg-secondary px-3'; const body = ( <> - - - - - + {content.primary != null ? ( @@ -103,7 +105,10 @@ export function SessionContextMetrics({ return ( {body} diff --git a/apps/mobile/src/components/agents/session-detail-content.tsx b/apps/mobile/src/components/agents/session-detail-content.tsx index 9b6c19abac0..4ace5e017b8 100644 --- a/apps/mobile/src/components/agents/session-detail-content.tsx +++ b/apps/mobile/src/components/agents/session-detail-content.tsx @@ -483,6 +483,7 @@ export function SessionDetailContent({ info={contextInfo} totalCostMicrodollars={totalMicrodollars} hasMessages={messages.length > 0} + loading={shouldShowLoading} onPress={ contextInfo ? () => {