Skip to content

feat(agent): live streaming subagent view with reopenable sub-threads - #3007

Merged
senamakel merged 8 commits into
tinyhumansai:mainfrom
senamakel:feat/subagent-live-processing
May 30, 2026
Merged

senamakel merged 8 commits into
tinyhumansai:mainfrom
senamakel:feat/subagent-live-processing

Conversation

@senamakel

@senamakel senamakel commented May 30, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Sub-agents now stream their processing live — reasoning and visible output arrive token-by-token instead of the whole result popping in at the end.
  • The chat timeline shows one row per delegation (was two: the spawn_subagent tool call and the subagent row).
  • A new drawer renders the delegation as a parent↔subagent chat: the parent's prompt opens it, then the sub-agent's turns (thinking → text → tool calls) render interleaved in the order they occurred.
  • Every spawn_subagent now persists a reopenable worker sub-thread, so the conversation survives navigation/restart and the drawer can rebuild it from memory.

Problem

Subagent activity was opaque: the UI showed static colored pills in the tool timeline and only surfaced the final message when the turn completed — no live view of what the child was thinking or doing. It also rendered the delegation as two confusing rows ("Research" tool call + "Researching" subagent), split text and tool calls into separate sections (losing the chronology of a real LLM turn), and ordinary spawn_subagent runs were ephemeral — once the live stream ended there was no way to reopen the loop.

Solution

  • Streaming (Rust): new AgentProgress::Subagent{Text,Thinking}Delta variants; the subagent runner builds a ProviderDelta streaming sink (mirroring the main turn loop) and forwards child deltas to the parent's on_progress, gated on a listener so CLI/triage/tests keep the non-streaming fast path. Bridged to subagent_text_delta / subagent_thinking_delta socket events.
  • Interleaved transcript (FE): SubagentActivity gains an ordered transcript (thinking/text/tool items); consecutive same-kind deltas extend the trailing item, tool calls slot in where they fired. The drawer renders this chronologically with per-turn dividers and a live cursor.
  • One row: onSubagentSpawned removes the originating spawn_subagent/delegate_* tool-call row and carries its prompt onto the subagent.
  • Persistence: shared create_worker_thread helper (reused by spawn_worker_thread) creates a worker-<uuid> thread linked to the parent (hidden from the sidebar, surfaced in the Workers tab) seeded with the prompt; worker_thread_id flows through the spawn event + turn-state snapshot. The drawer fetches that thread via threadApi.getThreadMessages when no live transcript is present (reopen-from-memory); the live transcript wins while streaming.

Design notes/tradeoffs: streamed text/thinking is display-only and not persisted to the turn-state snapshot (the child's final answer already lands in the thread); reopened transcripts therefore omit streamed reasoning. The dispatch / orchestration-ops / spawn_parallel_agents spawn paths still pass worker_thread_id: None (follow-up) — the common spawn_subagent path is fully wired.

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — added Rust + Vitest tests targeting the new/changed lines (runner delta ordering, slice reducers, drawer chat + reopen-from-memory, dedupe, worker-thread helper); CI diff-cover enforces the gate.
  • N/A: behaviour extends the existing agent/subagent surface — no new top-level feature ID rows in the coverage matrix.
  • N/A: no coverage-matrix feature IDs affected by this change.
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • N/A: not a release-cut surface — in-thread subagent chat UI, no manual-smoke surface touched.
  • N/A: no tracking issue for this work.

Impact

  • Desktop (the shipped target): in-thread subagent UX. Adds two socket event types and a worker_thread_id field (all additive/optional — older clients/snapshots stay parseable).
  • Storage: every spawn_subagent now writes a small worker sub-thread (parent-linked, so excluded from the main thread list). Streaming sink is only set up when a progress listener exists, so non-interactive runs are unaffected.
  • No migrations. No security surface change.

Related

  • Closes: N/A
  • Follow-up PR(s)/TODOs: wire worker_thread_id persistence into the dispatch / orchestration-ops / spawn_parallel_agents spawn paths.

AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/subagent-live-processing
  • Commit SHA: 5d0789f

Validation Run

  • pnpm --filter openhuman-app format:check (prettier --write on changed files + cargo fmt)
  • pnpm typecheck — clean
  • Focused tests: Vitest SubagentDrawer (8), chatRuntime transcript reducers (5), ChatRuntimeProvider (36, incl. dedupe), ToolTimelineBlock (12); cargo subagent_runner (44), turn_state (21), agent_orchestration (59), worker_thread helper
  • Rust fmt/check: cargo fmt + cargo check --bin openhuman-core clean
  • N/A: Tauri shell (app/src-tauri) not modified.

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: subagents stream live; one timeline row per delegation; drawer shows parent↔subagent chat; every subagent persists a reopenable sub-thread.
  • User-visible effect: live subagent reasoning/output + tool calls in a chat drawer, reopenable after navigation/restart.

Parity Contract

  • Legacy behavior preserved: streaming sink only attaches when a listener exists (CLI/triage/tests keep non-streaming path); all new event fields optional so older cores/snapshots render unchanged.
  • Guard/fallback/dispatch parity checks: drawer falls back to persisted thread when no live transcript; reducers no-op on unknown thread/row.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: N/A
  • Resolution: N/A

Summary by CodeRabbit

  • New Features

    • Sub-agent drawer: view live transcripts (thinking, text, tool calls), turn dividers, status, and a close action.
    • Timeline integration: “View Processing” button opens the drawer; sub-agent runs can be persisted and reopened from history.
  • Localization

    • Added sub-agent UI translations in 14 locales (including Arabic, Bengali, German, Spanish, French, Hindi, Indonesian, Italian, Korean, Polish, Portuguese, Russian, Chinese, and English).

Review Change Stack

senamakel added 4 commits May 29, 2026 20:59
Sub-agents previously ran non-streaming (provider.chat with stream: None)
and only emitted lifecycle counters, so their "processing" surfaced as
static colored pills that filled in after the run. The final message just
popped in at the end.

This streams a sub-agent's reasoning and visible output token-by-token
and gives it two UI surfaces: a richer live inline card and a
full-transcript drawer.

Core (Rust):
- progress.rs: new SubagentTextDelta / SubagentThinkingDelta variants
  (agent_id, task_id, delta, iteration).
- subagent_runner/ops.rs: the per-iteration provider.chat now builds a
  ProviderDelta streaming sink (mirroring session/turn.rs), maps child
  text/reasoning deltas onto the new variants, and forwards them to the
  parent's on_progress. Gated on a listener being attached so CLI / triage
  / tests keep the non-streaming fast path.
- channels/providers/web.rs: bridge arms emitting subagent_text_delta /
  subagent_thinking_delta socket events with delta + subagent detail.
- turn_state/mirror.rs + skills/run_log.rs: handle the new variants as
  live-only / non-persisted.

Frontend:
- chatService.ts: event types, listeners, EVENTS entries, registrations.
- chatRuntimeSlice.ts: SubagentActivity gains live-only streamingText /
  streamingThinking; new appendSubagentStreamDelta reducer.
- ChatRuntimeProvider.tsx: wires the two delta handlers to the matching
  subagent row.
- ToolTimelineBlock.tsx: the old pills become a richer card with a live
  one-line preview and a "View full processing" button.
- SubagentDrawer.tsx (new): slide-in panel with the full live transcript
  (streamed reasoning, Markdown output with cursor, child tool calls),
  re-derived from Redux so it streams live. Wired into Conversations.tsx.
- i18n: 10 new keys across en.ts + all 14 locale chunk files.

Tests: subagent_runner delta ordering/attribution test; turn_state mirror
unchanged-green; Vitest for the reducer, the card preview/button, and the
drawer.
…t chat

Two follow-ups to the subagent streaming work:

1. Collapse the duplicate timeline rows. A delegation previously showed
   TWO entries — the parent's `spawn_subagent`/`delegate_*` tool call
   ("Research") and the child `subagent:*` row ("Researching"). The spawn
   tool-call row is now removed when the subagent row is created
   (ChatRuntimeProvider.onSubagentSpawned), and its delegation prompt is
   carried onto the subagent as `prompt` for the drawer's opening turn.

2. Render the drawer as a parent↔subagent conversation. The delegation
   prompt opens it as a right-aligned "Parent" bubble (the input); the
   sub-agent replies below as its interleaved transcript (thinking, the
   text it produced, the tool calls that text triggered, the next turn).
   Adds `prompt` to SubagentActivity and a `conversations.subagent.parent`
   i18n key (en + all locale chunks).

Also fixes the colour tokens: the new card/drawer used non-existent
`ocean-*` classes (no-ops) — switched to the real brand `primary-*`.

Tests: provider dedupe+prompt-capture test; drawer parent-prompt + order
tests; existing suites green.
Make ordinary `spawn_subagent` delegations persist like dedicated worker
threads do, so the parent↔subagent conversation survives navigation and
restarts and can be reopened from memory.

Backend:
- New shared helper `agent_orchestration/tools/worker_thread.rs::create_worker_thread`
  — creates a `worker-<uuid>` thread linked to the parent (`parent_thread_id`,
  which hides it from the main sidebar; it surfaces in the Workers tab) and
  seeds it with the delegation prompt as the opening user message.
  `spawn_worker_thread` now reuses it; `spawn_subagent` calls it and passes
  the resulting `worker_thread_id` to the runner so each turn + tool result
  is appended to the same thread.
- `AgentProgress::SubagentSpawned` + `SubagentProgressDetail` carry
  `worker_thread_id`; web.rs bridges it on the `subagent_spawned` event;
  turn-state mirror persists it so a cold-boot snapshot can reopen too.
- Other emitters (dispatch / orchestration ops / parallel) pass None for now.

Frontend:
- SubagentActivity + PersistedSubagentActivity gain `workerThreadId`; set on
  spawn and carried through snapshot rehydration.
- SubagentDrawer reopens from memory: when there's no live transcript but a
  worker thread backs the row, it fetches that thread's messages
  (threadApi.getThreadMessages) and rebuilds the conversation (prompt + tool
  calls + text). Live transcript still wins while streaming.

Tests: worker_thread helper (thread linked + prompt seeded); drawer
reopen-from-memory + no-fetch-when-live; existing Rust + Vitest suites green.
@senamakel
senamakel requested a review from a team May 30, 2026 06:02
@coderabbitai

coderabbitai Bot commented May 30, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 42448b48-173b-4d07-94f7-25a2d0488700

📥 Commits

Reviewing files that changed from the base of the PR and between 8d39bd5 and 6fab7ac.

📒 Files selected for processing (5)
  • CLAUDE.md
  • app/src/pages/conversations/components/SubagentDrawer.tsx
  • app/src/store/__tests__/chatRuntimeSlice.subagentStream.test.ts
  • app/src/store/chatRuntimeSlice.ts
  • src/openhuman/agent/harness/subagent_runner/ops.rs
✅ Files skipped from review due to trivial changes (1)
  • CLAUDE.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/openhuman/agent/harness/subagent_runner/ops.rs
  • app/src/store/tests/chatRuntimeSlice.subagentStream.test.ts
  • app/src/store/chatRuntimeSlice.ts
  • app/src/pages/conversations/components/SubagentDrawer.tsx

📝 Walkthrough

Walkthrough

Streams subagent thinking/text deltas from providers into AgentProgress, emits web-channel events, subscribes in frontend chat service, updates Redux transcript state, and surfaces live or persisted subagent transcripts in a new SubagentDrawer UI; worker threads are persisted when possible and i18n keys added across locales.

Changes

Subagent Transcript Streaming & Display

Layer / File(s) Summary
Backend progress events
src/openhuman/agent/progress.rs
AgentProgress::SubagentSpawned gains optional worker_thread_id; new SubagentTextDelta and SubagentThinkingDelta variants added.
Provider delta streaming
src/openhuman/agent/harness/subagent_runner/ops.rs, ops_tests.rs
Provider deltas (text/thinking) are streamed via mpsc to the parent progress sink and forwarded as AgentProgress events; tests added.
Socket.IO bridge & turn-state
src/core/socketio.rs, src/openhuman/channels/providers/web.rs, src/openhuman/threads/turn_state/mirror.rs, types.rs
Web-channel emits subagent_spawned with worker_thread_id and delta events; TurnState persists worker_thread_id and ignores transient deltas.
Frontend Redux state model
app/src/store/chatRuntimeSlice.ts, app/src/types/turnState.ts
SubagentActivity extended with workerThreadId, prompt, transcript; new SubagentTranscriptItem union; rehydration rebuilds transcript from persisted toolCalls.
Chat service subscription
app/src/services/chatService.ts, app/src/services/__tests__/chatService.subagentDelta.test.ts
Defines subagent delta event interfaces, expands ChatEventListeners, registers subagent_text_delta/subagent_thinking_delta handlers, and adds tests for handler registration/dispatch.
Redux reducers for transcript
app/src/store/chatRuntimeSlice.ts, app/src/store/__tests__/chatRuntimeSlice.subagentStream.test.ts
Adds appendSubagentStreamDelta, recordSubagentTranscriptTool, resolveSubagentTranscriptTool reducers and tests for merging, ordering, de-duplication, and resolution.
Runtime provider wiring
app/src/providers/ChatRuntimeProvider.tsx, __tests__/ChatRuntimeProvider.test.tsx
Registers delta listeners, collapses parent spawn row into subagent entry preserving prompt, initializes workerThreadId/transcript, records/resolves tool calls, and tests spawn collapse and delta handling.
SubagentDrawer UI component
app/src/pages/conversations/components/SubagentDrawer.tsx, __tests__/SubagentDrawer.test.tsx
New drawer renders live or reconstructed transcripts (fetching thread messages when workerThreadId present), shows running cursor, group-by-iteration, tool elapsed/status, and supports Escape/backdrop close; tests added.
ToolTimelineBlock preview & affordance
app/src/pages/conversations/components/ToolTimelineBlock.tsx, __tests__/ToolTimelineBlock.test.tsx
Adds inline transcript preview (prefer text over thinking), SUBAGENT_PREVIEW_CHARS, optional onView/onViewSubagent callback and "view processing" button; tests for preview priority and interaction.
Conversations page wiring
app/src/pages/Conversations.tsx
Adds openSubagentTaskId state, derives selected subagent entry from timeline, wires onViewSubagent in both timeline render paths, and renders SubagentDrawer.
Worker thread persistence helper
src/openhuman/agent_orchestration/tools/worker_thread.rs, spawn_subagent.rs, spawn_worker_thread.rs, tools.rs
Adds create_worker_thread helper to persist worker threads; spawn_subagent best-effort creates worker thread and threads worker_thread_id into events/options; refactors worker-thread tooling; tests added.
Localization updates
CLAUDE.md, app/src/lib/i18n/*.ts
Adds conversations.subagent.* keys across locale files and updates i18n guidance to require real non-English translations enforced by CI.
Logging
src/openhuman/skills/run_log.rs
Suppress SubagentTextDelta and SubagentThinkingDelta from per-step logs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • oxoxDev
  • M3gA-Mind

Poem

🐰 I hopped through streams of thought and text,
threads that worker-rabbits nest;
in drawers they hum, both live and stored,
translation keys across the world restored.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: live streaming of subagent processing with the ability to reopen conversations from persistent worker sub-threads.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

senamakel added 2 commits May 29, 2026 23:19
Resolves the i18n conflict from upstream tinyhumansai#3004 (chunked
chunks/<locale>-N.ts layout retired → single flat <locale>.ts files):
- Accept upstream's deletion of all chunks/* files.
- Re-home the conversations.subagent.* keys into en.ts (already auto-merged)
  and add them to every flat locale file with REAL translations (not English
  placeholders) — satisfies both i18n:check (parity) and i18n:english:check
  (no untranslated English).
- CLAUDE.md i18n rule updated: locale files must carry actual translations,
  never English placeholders.
The diff-coverage gate (≥80% on changed lines) flagged the new subagent
streaming wiring as under-covered:
- chatService.ts subagent_text_delta / subagent_thinking_delta socket
  registration (was 12.5%) — new chatService.subagentDelta test registers
  both via a fake socket, fires each event, and asserts the listener fires
  (+ the no-listener and no-socket paths).
- ChatRuntimeProvider onSubagentTextDelta / onSubagentThinkingDelta handlers
  (was 28.6%) — new tests append a streamed text+thinking delta to the
  subagent transcript, plus the guard path that drops deltas missing
  task/agent/delta.
@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. labels May 30, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/providers/ChatRuntimeProvider.tsx (1)

470-497: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Deduplicate subagent rows when subagent_spawned is re-delivered.

Line 470 builds a new subagent row every time, but only removes spawnEntryId. If the same spawn event is delivered twice, you end up with duplicate ids in the timeline.

💡 Proposed fix
-        const base = pendingContext.spawnEntryId
-          ? existing.filter(e => e.id !== pendingContext.spawnEntryId)
-          : existing;
+        const subagentRowId = `${event.thread_id}:subagent:${event.skill_id}:${event.tool_name}`;
+        const base = existing.filter(
+          e => e.id !== pendingContext.spawnEntryId && e.id !== subagentRowId
+        );
         dispatch(
           setToolTimelineForThread({
             threadId: event.thread_id,
             entries: [
               ...base,
               decorateEntry({
-                id: `${event.thread_id}:subagent:${event.skill_id}:${event.tool_name}`,
+                id: subagentRowId,
                 name: `subagent:${event.tool_name}`,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/providers/ChatRuntimeProvider.tsx` around lines 470 - 497, The code
always appends a new subagent entry (built via decorateEntry with id
`${event.thread_id}:subagent:${event.skill_id}:${event.tool_name}`) but only
removes pendingContext.spawnEntryId, which allows duplicate entries when the
same spawn event is re-delivered; update the logic in the
setToolTimelineForThread dispatch to compute the newSubagentId (the same
template above) and filter existing entries to remove both
pendingContext.spawnEntryId (if present) and any entry whose id equals
newSubagentId before appending the decorated entry, or alternatively deduplicate
by id after building the new entries array so the timeline contains at most one
entry per id.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/pages/conversations/components/SubagentDrawer.tsx`:
- Around line 121-124: When workerThreadId changes while needsFetch is true we
must clear stale transcript state so the drawer doesn't show the previous
thread's data; update the effect or fetch logic that depends on
workerThreadId/needsFetch (the state variables fetched and setFetched and the
hook that triggers the fetch) to setFetched(null) (or a dedicated "loading"
state) immediately when workerThreadId changes or when a new fetch is initiated,
then populate fetched only after the new request resolves; ensure the
cleanup/cancel path also doesn't repopulate fetched for an old request (use a
request id or abort controller tied to workerThreadId) so only the current
thread's response updates fetched.
- Line 305: SubagentDrawer renders raw enum values via item.status; change it to
use localized labels by passing item.status through the translation hook useT()
(or a small mapping helper) and render the translated string instead of the raw
enum. Specifically, import/use useT() in SubagentDrawer.tsx, create a mapping or
helper like getStatusLabel(status) that calls t('subagent.status.running'),
t('subagent.status.success'), t('subagent.status.error') (or similar keys), and
replace <span className={`ml-auto ${callTone}`}>{item.status}</span> with the
translated label; ensure all enum branches are covered and keys are added to the
i18n resource bundle.

In `@app/src/store/chatRuntimeSlice.ts`:
- Around line 325-329: The transcript merging logic currently only checks
last.kind and will append delta across different iterations; update the merge
condition in the block handling transcript updates (the variables last,
transcript, kind, iteration) to require both last.kind === kind AND
last.iteration === iteration (or equivalent) before concatenating last.text +=
delta, otherwise always push a new { kind, iteration, text: delta } entry to
preserve turn boundaries.

In `@CLAUDE.md`:
- Line 369: Unify the contradictory i18n guidance by making the policy
consistent: update the paragraph that references en.ts, INTENTIONAL_ENGLISH, and
the checks (pnpm i18n:check and pnpm i18n:english:check /
scripts/i18n-find-english.ts) so it clearly states that all non-English locale
files must contain real translations (no English fallbacks), and keep the
INTENTIONAL_ENGLISH allowlist description as the only exception for genuine
brand/command/path/unit literals; remove or rewrite the sentence that implies
other locales may fall back to English so the document consistently enforces
translation parity against en.ts.

In `@src/openhuman/agent/harness/subagent_runner/ops.rs`:
- Around line 1503-1520: The provider.chat(...).await? can return early and skip
the cleanup of the streaming forwarder; change the flow to capture the Result
from provider.chat (call provider.chat in provider.chat(...).await and store
e.g. resp_res), then always perform the cleanup: drop(delta_tx_opt) and if let
Some(forwarder) = delta_forwarder { let _ = forwarder.await; } before
propagating the error (i.e. return resp_res? or map_err), ensuring symbols
provider.chat, delta_tx_opt, delta_forwarder, and forwarder are used exactly as
in the diff so the forwarder task is awaited even when chat fails.

---

Outside diff comments:
In `@app/src/providers/ChatRuntimeProvider.tsx`:
- Around line 470-497: The code always appends a new subagent entry (built via
decorateEntry with id
`${event.thread_id}:subagent:${event.skill_id}:${event.tool_name}`) but only
removes pendingContext.spawnEntryId, which allows duplicate entries when the
same spawn event is re-delivered; update the logic in the
setToolTimelineForThread dispatch to compute the newSubagentId (the same
template above) and filter existing entries to remove both
pendingContext.spawnEntryId (if present) and any entry whose id equals
newSubagentId before appending the decorated entry, or alternatively deduplicate
by id after building the new entries array so the timeline contains at most one
entry per id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1396d558-b0ee-4a86-a74b-f5a436727d57

📥 Commits

Reviewing files that changed from the base of the PR and between c7e9d85 and 8d39bd5.

📒 Files selected for processing (43)
  • CLAUDE.md
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/pages/Conversations.tsx
  • app/src/pages/conversations/components/SubagentDrawer.tsx
  • app/src/pages/conversations/components/ToolTimelineBlock.tsx
  • app/src/pages/conversations/components/__tests__/SubagentDrawer.test.tsx
  • app/src/pages/conversations/components/__tests__/ToolTimelineBlock.test.tsx
  • app/src/providers/ChatRuntimeProvider.tsx
  • app/src/providers/__tests__/ChatRuntimeProvider.test.tsx
  • app/src/services/__tests__/chatService.subagentDelta.test.ts
  • app/src/services/chatService.ts
  • app/src/store/__tests__/chatRuntimeSlice.subagentStream.test.ts
  • app/src/store/chatRuntimeSlice.ts
  • app/src/types/turnState.ts
  • src/core/socketio.rs
  • src/openhuman/agent/harness/subagent_runner/ops.rs
  • src/openhuman/agent/harness/subagent_runner/ops_tests.rs
  • src/openhuman/agent/progress.rs
  • src/openhuman/agent_orchestration/ops.rs
  • src/openhuman/agent_orchestration/tools.rs
  • src/openhuman/agent_orchestration/tools/dispatch.rs
  • src/openhuman/agent_orchestration/tools/spawn_parallel_agents.rs
  • src/openhuman/agent_orchestration/tools/spawn_subagent.rs
  • src/openhuman/agent_orchestration/tools/spawn_worker_thread.rs
  • src/openhuman/agent_orchestration/tools/worker_thread.rs
  • src/openhuman/channels/providers/web.rs
  • src/openhuman/skills/run_log.rs
  • src/openhuman/threads/turn_state/mirror.rs
  • src/openhuman/threads/turn_state/mirror_tests.rs
  • src/openhuman/threads/turn_state/types.rs

Comment thread app/src/pages/conversations/components/SubagentDrawer.tsx
Comment thread app/src/pages/conversations/components/SubagentDrawer.tsx Outdated
Comment thread app/src/store/chatRuntimeSlice.ts Outdated
Comment thread CLAUDE.md
Comment thread src/openhuman/agent/harness/subagent_runner/ops.rs Outdated
- SubagentDrawer: tag the reopen-fetched transcript with its workerThreadId
  and only render it when it matches the current row, so switching subagents
  can't briefly show a previous thread's conversation; clear stale state
  when a new fetch starts.
- SubagentDrawer: localize the transcript tool-call status label via useT()
  instead of rendering the raw running/success/error enum.
- chatRuntimeSlice: only merge adjacent same-kind transcript deltas when they
  share the same iteration, so two same-kind chunks from different turns
  (no tool call between) don't fuse into one entry.
- subagent_runner: drop the stream sender + join the forwarder on BOTH the
  success and error paths (was leaking the task when provider.chat errored
  via early `?`).
- CLAUDE.md: reconcile the i18n guidance — English fallback is the runtime
  safety net for missing keys, not a license to ship untranslated values;
  real translations required in every locale.
@senamakel
senamakel merged commit 3556842 into tinyhumansai:main May 30, 2026
18 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant