Skip to content

fix(ui): manually created tasks render as "Unnamed task" in the sidebar - #407

Merged
jromualdez-scale merged 2 commits into
mainfrom
jerome/agx1-810-unnamed-task-sidebar-fix
Aug 19, 2026
Merged

fix(ui): manually created tasks render as "Unnamed task" in the sidebar#407
jromualdez-scale merged 2 commits into
mainfrom
jerome/agx1-810-unnamed-task-sidebar-fix

Conversation

@jromualdez-scale

@jromualdez-scale jromualdez-scale commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Every task created by typing into the prompt box renders as "Unnamed task" in the sidebar. The message and reply are fine — only the label is wrong. Scheduled tasks are unaffected.

#377 made the list-tasks response a lean TaskSummary that omits params (correctly — params is the arbitrary caller-supplied create-time payload and can carry sensitive material, so it must not be exposed in bulk). The sidebar's label resolver was repointed accordingly, from params.description to task_metadata.display_nametask.name. But the writer was never updated to match: the prompt box still created tasks with only params.description, which the sidebar can no longer see, so the label fell all the way through to the default.

Fix

Frontend-only — the backend already accepts and persists task_metadata on task/create and returns it in both the create and list responses:

  • prompt-input.tsx now writes the label the resolver reads first: task_metadata: { display_name: deriveTaskDisplayName(prompt) }.
  • deriveTaskDisplayName (in task-utils.ts, next to the reader) trims, collapses whitespace/newlines, and truncates to 80 chars.
  • useCreateTask now plumbs task_metadata through to the RPC body; previously anything besides agentName/params was silently dropped.

The label renders immediately on create (the optimistic cache insert uses the create response, which carries task_metadata) and correctly after reload (the list response includes task_metadata).

Deliberately not used: task.name. It looks like the obvious fix given the resolver's fallback, but name is a globally-unique get-or-create idempotency key: task/create with an existing name returns that task (and can overwrite its params). Writing prompts into it would silently merge unrelated conversations — a data-correctness bug worse than the cosmetic one being fixed.

Trade-off, stated explicitly: this intentionally publishes a normalized 80-char prefix of the prompt into task_metadata, which the broadly-scoped list response includes. That is strictly less exposure than pre-#377 behavior (full params, including the full prompt, in every list item), and it is the same mechanism the scheduler already uses to title tasks — but display_name should be treated as a public-ish display field, and nothing sensitive should ever be auto-derived into it beyond this.

Tests

  • task-utils.test.ts: unit coverage for deriveTaskDisplayName, plus a writer/reader contract test — a task shaped like the prompt-box writer's output must not resolve to "Unnamed task". The absence of exactly this test is how the writer and reader drifted apart unnoticed.
  • use-create-task.test.tsx (new): asserts the mutation forwards task_metadata in the task/create request body, and sends null when omitted.

Not addressed here

  • Tasks created after fix(tasks): omit params from the list-tasks response #377 with null task_metadata keep their default label (no backfill; cosmetic).
  • The stock notebook template in the Python SDK repo sets name (an idempotency key) as its only human-visible identifier, which now surfaces in the sidebar as <uuid>-task; fixing that to also set display_name is a follow-up in that repo.

Verification

  • npm run typecheck, npm run lint, npm test — all green (82 tests, 7 new).

🤖 Generated with Claude Code

Greptile Summary

The PR aligns manually created task labels with the sidebar’s metadata-based reader.

  • Derives a normalized display name from the submitted prompt.
  • Forwards task metadata through the task-creation hook.
  • Adds coverage for metadata forwarding and task-name normalization.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
agentex-ui/components/primary-content/prompt-input.tsx Adds a normalized prompt-derived display name to newly created task metadata.
agentex-ui/hooks/use-create-task.ts Extends task creation to forward optional task metadata to the RPC.
agentex-ui/lib/task-utils.ts Adds the display-name normalization and truncation helper.
agentex-ui/hooks/use-create-task.test.tsx Verifies task metadata is forwarded and omitted metadata is sent as null.
agentex-ui/lib/task-utils.test.ts Covers normalization, code-point truncation, and the writer/reader naming contract.

Sequence Diagram

sequenceDiagram
  participant User
  participant Input as PromptInput
  participant Hook as useCreateTask
  participant API as task/create
  participant Sidebar
  User->>Input: Submit prompt
  Input->>Input: Derive display_name
  Input->>Hook: params + task_metadata
  Hook->>API: Create task
  API-->>Hook: Task with task_metadata
  Hook-->>Sidebar: Seed task cache
  Sidebar->>Sidebar: Resolve display_name
Loading

Reviews (2): Last reviewed commit: "fix(ui): truncate display_name by code p..." | Re-trigger Greptile

Context used:

…prompt box

Since #377 the list-tasks response omits `params`, and the sidebar label
resolver reads `task_metadata.display_name` then `task.name`. The prompt-box
writer was never updated to match: it still set only `params.description`,
which the sidebar can no longer see, so every manually created task rendered
as "Unnamed task".

Write the label into `task_metadata.display_name` at creation (prompt text,
whitespace-collapsed, truncated to 80 chars) and plumb `task_metadata`
through useCreateTask, which previously dropped it. `task.name` is left
untouched: it is a globally-unique get-or-create idempotency key, and
writing prompts into it would silently merge unrelated tasks.

Adds a writer/reader contract test so the label source and the label
writer can't drift apart silently again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jromualdez-scale
jromualdez-scale marked this pull request as ready for review August 18, 2026 18:08
@jromualdez-scale
jromualdez-scale requested a review from a team as a code owner August 18, 2026 18:08
Comment thread agentex-ui/lib/task-utils.ts Outdated
…ogate pairs

A UTF-16 unit-based slice(0, 80) can cut an astral character (e.g. emoji)
in half at the boundary, producing a lone surrogate. Postgres rejects lone
surrogates in JSONB, so the whole task/create request would fail. Truncate
by code points instead, and cover the boundary case in tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jromualdez-scale
jromualdez-scale merged commit 304f014 into main Aug 19, 2026
15 checks passed
@jromualdez-scale
jromualdez-scale deleted the jerome/agx1-810-unnamed-task-sidebar-fix branch August 19, 2026 00:28
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.

3 participants