Skip to content

feat(mobile): notify when agent sessions need input#4545

Open
iscekic wants to merge 2 commits into
mainfrom
feature/mobile-session-attention-notifications
Open

feat(mobile): notify when agent sessions need input#4545
iscekic wants to merge 2 commits into
mainfrom
feature/mobile-session-attention-notifications

Conversation

@iscekic

@iscekic iscekic commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • notify mobile users when remote CLI or interactive Cloud Agent sessions require a question, permission, or blocking-suggestion response
  • persist attention requests in a durable session outbox with replay deduplication, resolution cancellation, bounded retry, and exact-session presence suppression
  • add mobile blocking-suggestion actions and exact-session presence on mobile and web

Verification

  • scripts/typecheck-all.sh --changes-only
  • pnpm lint
  • mobile: 101 files / 561 tests, format check, unused export check
  • session ingest: 497 unit and 88 Workers integration tests
  • Cloud Agent: 2,273 tests, 3 skipped
  • notifications: 106 tests
  • event service: 33 tests
  • session-ingest contracts: 11 tests
  • web exact-session presence hook: 4 tests
  • iOS device E2E: question reply, permission response, blocking suggestion accept/dismiss, interaction precedence, composer suppression, and exact-session presence release/isolation

E2E limitation

  • OS push appearance and notification tap-through were not exercised locally because Expo push delivery credentials/device-token delivery were unavailable; notification payload and routing remain covered by service tests.
  • The local fake LLM cannot emit Cloud Agent question tool calls, so Cloud Agent question production is covered at wrapper/service boundaries rather than device E2E.

@iscekic iscekic self-assigned this Jul 14, 2026
Comment thread services/cloud-agent-next/src/websocket/ingest-attention-classifier.ts Outdated
Comment thread services/cloud-agent-next/src/websocket/ingest.ts
Comment thread services/session-ingest/src/dos/SessionIngestDO.ts
Comment thread services/session-ingest/src/attention-outbox-store.ts Outdated
Comment thread services/session-ingest/src/attention-outbox.ts
Comment thread apps/mobile/src/components/agents/session-detail-content.tsx
@kilo-code-bot

kilo-code-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 4
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
services/session-ingest/src/dos/attention-event-input.ts 24 Remote CLI resolve events are rejected by the new required reason
packages/session-ingest-contracts/src/rpc-contract.ts 651 Required resolve reasons break rolling deployment compatibility
services/session-ingest/src/dos/attention-alarm.ts 95 Pre-deployment metrics alarms are discarded without emission
services/session-ingest/src/attention-outbox-store.ts 340 Every claim materializes the entire due queue
Files Reviewed (19 files)
  • apps/mobile/src/components/agents/session-detail-content.tsx - 0 issues
  • packages/session-ingest-contracts/src/rpc-contract.test.ts - 0 issues
  • packages/session-ingest-contracts/src/rpc-contract.ts - 1 issue
  • services/cloud-agent-next/src/persistence/CloudAgentSession.test.ts - 0 issues
  • services/cloud-agent-next/src/persistence/cloud-agent-attention-scheduler.ts - 0 issues
  • services/cloud-agent-next/src/websocket/ingest-attention-classifier.test.ts - 0 issues
  • services/cloud-agent-next/src/websocket/ingest-attention-classifier.ts - 0 issues
  • services/cloud-agent-next/src/websocket/ingest.test.ts - 0 issues
  • services/session-ingest/src/attention-outbox-store.ts - 1 issue
  • services/session-ingest/src/attention-outbox.test.ts - 0 issues
  • services/session-ingest/src/attention-outbox.ts - 0 issues
  • services/session-ingest/src/dos/SessionIngestDO.ts - 0 issues
  • services/session-ingest/src/dos/attention-alarm.test.ts - 0 issues
  • services/session-ingest/src/dos/attention-alarm.ts - 1 issue
  • services/session-ingest/src/dos/attention-event-input.test.ts - 0 issues
  • services/session-ingest/src/dos/attention-event-input.ts - 1 issue
  • services/session-ingest/src/session-ingest-rpc.test.ts - 0 issues
  • services/session-ingest/src/session-ingest-rpc.ts - 0 issues
  • services/session-ingest/test/integration/session-attention-outbox.test.ts - 0 issues

Fix these issues in Kilo Cloud

Previous Review Summary (commit 98be1fc)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 98be1fc)

Status: 6 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 6
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
services/cloud-agent-next/src/websocket/ingest-attention-classifier.ts 62 Resolve events read id instead of the SDK's requestID
services/cloud-agent-next/src/websocket/ingest.ts 745 Child-session waits are recorded under the root session
services/session-ingest/src/dos/SessionIngestDO.ts 803 Immediate attention alarms emit metrics before their deadline
services/session-ingest/src/attention-outbox-store.ts 168 Resolve-before-raise ordering can create stale pending pushes
services/session-ingest/src/attention-outbox.ts 105 Retry horizon exceeds the notification deduplication TTL
apps/mobile/src/components/agents/session-detail-content.tsx 504 Replacement suggestions inherit stale pending card state
Files Reviewed (50 files)
  • apps/mobile/src/components/agents/interaction-surface.test.ts - 0 issues
  • apps/mobile/src/components/agents/interaction-surface.ts - 0 issues
  • apps/mobile/src/components/agents/session-detail-content.tsx - 1 issue
  • apps/mobile/src/components/agents/suggestion-card.test.tsx - 0 issues
  • apps/mobile/src/components/agents/suggestion-card.tsx - 0 issues
  • apps/mobile/src/components/kilo-chat/hooks/use-agent-session-presence.test.ts - 0 issues
  • apps/mobile/src/components/kilo-chat/hooks/use-agent-session-presence.ts - 0 issues
  • apps/mobile/vitest.config.ts - 0 issues
  • apps/web/src/components/cloud-agent-next/CloudChatPage.tsx - 0 issues
  • apps/web/src/hooks/useAgentSessionPresence.test.ts - 0 issues
  • apps/web/src/hooks/useAgentSessionPresence.ts - 0 issues
  • packages/event-service/src/__tests__/presence.test.ts - 0 issues
  • packages/event-service/src/presence.ts - 0 issues
  • packages/notifications/src/rpc-schemas.ts - 0 issues
  • packages/notifications/src/rpc-schemas.type-test.ts - 0 issues
  • packages/session-ingest-contracts/package.json - 0 issues
  • packages/session-ingest-contracts/src/rpc-contract.test.ts - 0 issues
  • packages/session-ingest-contracts/src/rpc-contract.ts - 0 issues
  • packages/session-ingest-contracts/vitest.config.ts - 0 issues
  • pnpm-lock.yaml - generated, not reviewed
  • services/cloud-agent-next/src/persistence/CloudAgentSession.test.ts - 0 issues
  • services/cloud-agent-next/src/persistence/CloudAgentSession.ts - 0 issues
  • services/cloud-agent-next/src/persistence/cloud-agent-attention-scheduler.ts - 0 issues
  • services/cloud-agent-next/src/websocket/ingest-attention-classifier.test.ts - 0 issues
  • services/cloud-agent-next/src/websocket/ingest-attention-classifier.ts - 1 issue
  • services/cloud-agent-next/src/websocket/ingest.test.ts - 0 issues
  • services/cloud-agent-next/src/websocket/ingest.ts - 1 issue
  • services/notifications/src/index.ts - 0 issues
  • services/notifications/src/lib/cloud-agent-session-push.ts - 0 issues
  • services/notifications/src/lib/notifications-service-cloud-agent.test.ts - 0 issues
  • services/session-ingest/drizzle/0003_session_attention_outbox.sql - 0 issues
  • services/session-ingest/drizzle/meta/0003_snapshot.json - generated, not reviewed
  • services/session-ingest/drizzle/meta/_journal.json - generated, not reviewed
  • services/session-ingest/drizzle/migrations.js - 0 issues
  • services/session-ingest/src/attention-outbox-store.ts - 1 issue
  • services/session-ingest/src/attention-outbox.test.ts - 0 issues
  • services/session-ingest/src/attention-outbox.ts - 1 issue
  • services/session-ingest/src/db/sqlite-schema.ts - 0 issues
  • services/session-ingest/src/dos/SessionIngestDO.test.ts - 0 issues
  • services/session-ingest/src/dos/SessionIngestDO.ts - 1 issue
  • services/session-ingest/src/dos/UserConnectionDO.test.ts - 0 issues
  • services/session-ingest/src/dos/UserConnectionDO.ts - 0 issues
  • services/session-ingest/src/dos/attention-alarm.test.ts - 0 issues
  • services/session-ingest/src/dos/attention-alarm.ts - 0 issues
  • services/session-ingest/src/dos/attention-event-input.test.ts - 0 issues
  • services/session-ingest/src/dos/attention-event-input.ts - 0 issues
  • services/session-ingest/src/notifications-binding.ts - 0 issues
  • services/session-ingest/src/session-ingest-rpc.test.ts - 0 issues
  • services/session-ingest/src/session-ingest-rpc.ts - 0 issues
  • services/session-ingest/test/integration/session-attention-outbox.test.ts - 0 issues

Fix these issues in Kilo Cloud


Reviewed by gpt-5.6-sol · Input: 142.7K · Output: 16.3K · Cached: 1M

Review guidance: REVIEW.md from base branch main

@iscekic

iscekic commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Duplicate of #4445

@iscekic iscekic marked this as a duplicate of #4445 Jul 14, 2026
// action, so the producer ignores it.
export const attentionIntentSchema = z.discriminatedUnion('kind', [
z.object({ kind: z.literal('raise'), reason: attentionReasonSchema }),
z.object({ kind: z.literal('resolve'), reason: attentionReasonSchema }),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Remote CLI resolves are rejected by the tightened schema

UserConnectionDO.recordAttentionEvent still maps every resolve to { kind: 'resolve' } without forwarding intent.reason. This schema now rejects those calls as invalid_input, and the caller ignores that result, so remote-CLI questions, permissions, and suggestions remain pending after the user responds and can still send stale pushes. Update that producer in the same rollout or accept the previous shape at this boundary.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

const cloudAgentAttentionReasonSchema = z.enum(['question', 'permission']);
export const cloudAgentAttentionIntentSchema = z.discriminatedUnion('kind', [
z.object({ kind: z.literal('raise'), reason: cloudAgentAttentionReasonSchema }),
z.object({ kind: z.literal('resolve'), reason: cloudAgentAttentionReasonSchema }),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Requiring reason breaks rolling deployment compatibility

The currently deployed Cloud Agent producer from the previous revision sends { kind: 'resolve' }. If session-ingest is deployed before the updated producer, this boundary rejects every resolve as invalid_input, leaving raised notifications pending until the producer rollout completes. Preserve the old resolve shape during the rollout or enforce producer-first deployment before tightening the shared RPC contract.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

// but accept the boolean `true` as well so a future refactor that
// passes the parsed value through stays safe.
if (metricsEmitted === 'true' || metricsEmitted === true) return false;
if (metricsAlarmAt === null || metricsAlarmAt === undefined) return false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Existing metrics alarms are discarded after deployment

DOs whose alarms were scheduled by the pre-PR code have a platform alarm but no persisted metricsAlarmAt. Returning false here makes that already-fired alarm skip emission, and the final rescheduleAlarm() then finds no persisted work and deletes it, permanently losing those session metrics. The missing-deadline case needs to preserve the legacy behavior for alarms that span deployment.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

)
)
.orderBy(asc(attentionOutbox.next_attempt_at))
.all();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Each claim materializes the entire due queue

This replaces the indexed LIMIT 1 claim with .all(), even though the function leases only one row. dispatchOutboxBatch calls it up to 25 times, so a large per-session backlog repeatedly allocates and scans the remaining queue and can exhaust Durable Object CPU or memory before it drains. Keep the deadline predicate in the query and select a bounded candidate instead of materializing every due row on each claim.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant