Skip to content

Conversation

@ssncferreira
Copy link
Contributor

@ssncferreira ssncferreira commented Nov 21, 2025

Problem

Tasks currently only expose a machine-friendly name field (e.g. task-python-debug-a1b2), but this value is primarily an identifier rather than a clean, descriptive label. We need a separate display-friendly name for use in the UI.

This PR introduces a new display_name field and updates the task-name generation flow. The Claude system prompt was updated to return valid JSON with both name and display_name. The name generation logic follows a fallback chain (Anthropic > prompt sanitization > random fallback). To make task names more closely resemble their display names, the legacy task- prefix has been removed. For context, PR #20834 introduced a small Task icon to the workspace list to help identify workspaces associated to tasks.

Changes

  • Database migration: Added display_name column to tasks table
  • Updated system prompt to generate both task name and display name as valid JSON
  • Task name generation now follows a fallback chain: Anthropic > prompt sanitization > random fallback
  • Removed task- prefix from task names to allow more descriptive names
  • Note: PR feat: associate task icon with workspaces #20834 adds a Task icon to workspaces in the workspace list to distinguish task-created workspaces

Note: UI changes will be addressed in a follow-up PR

Related to: #20801

@ssncferreira ssncferreira force-pushed the ssncferreira/feat-task-display-name branch 4 times, most recently from 976ef82 to 64b6b10 Compare November 21, 2025 14:46

-- Recreate view without the display_name column.
-- This restores the view to its previous state after removing display_name from tasks.
CREATE VIEW
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems adding the view recreation is required on both migrations, because otherwise sqlc would not generate the Task structure with DisplayName on up. AFAIU, since our queries all use tasks_with_status view and not the tasks table, PostgreSQL doesn't automatically update the view definition. That is why we need to force PostgreSQL to re-expand the tasks.* wildcard and pick up the new column. Let me know if there is a cleaner way of doing this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately this is the way ™️

Copy link
Member

Choose a reason for hiding this comment

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

We need to get this implemented in our sqlc fork: Emyrk/sqlc#1

@ssncferreira ssncferreira force-pushed the ssncferreira/feat-task-display-name branch from 64b6b10 to 9ecbe62 Compare November 21, 2025 15:28
@ssncferreira ssncferreira marked this pull request as ready for review November 21, 2025 15:29
return aisdk.AnthropicToDataStream(client.Messages.NewStreaming(ctx, anthropic.MessageNewParams{
Model: model,
MaxTokens: 24,
MaxTokens: 50,
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you hit the limit of 24? I'm not entirely sure what this limit should be but just want to make sure we're not at risk of running over

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I hit the limit with 24 😕 the JSON would be incomplete and parsing would fail. I bumped it to 50 after testing with the maximum characters we could generate.

According to Anthropic's documentation, Claude uses approximately 3.5 characters per token for English text. Our max output is:

  • Base JSON structure: {"task_name":"","display_name":""} = 43 chars
  • Task name: 27 chars max
  • Display name: 64 chars max
  • Total: 134 characters ≈ 38 tokens

So, I guess 50 tokens gives us a comfortable buffer above the theoretical max, accounting for tokenization variance and any extra whitespace Claude might add 🤷‍♀️

Copy link
Contributor Author

@ssncferreira ssncferreira Nov 21, 2025

Choose a reason for hiding this comment

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

@DanielleMaywood How did you come up with 24 the first time? 🤔
I can add these calculations as a comment if that helps

Copy link
Contributor

Choose a reason for hiding this comment

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

I used one of those tools that tells you how many tokens are in a message, added a few for leeway and doubled it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tested the max output with anthropics token counting API: https://platform.claude.com/docs/en/build-with-claude/token-counting#count-tokens-in-basic-messages
It seems this endpoint is for input messages, but I assume the tokenization should be identical for both input and output. The endpoint returned 70 tokens, so I've updated this to be 100 for a safety buffer: 39d3805

}
generatedTaskName := taskname.Generate(ctx, req.Input)
taskName = generatedTaskName.Name
displayName = generatedTaskName.DisplayName
Copy link
Member

Choose a reason for hiding this comment

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

This behavior will be a bit weird if the user specifies a name. There's two options as I see it:

  1. Allow them to manually specify it in the request
  2. Always generate name/display name, only assign name if empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, I completely missed that! I've updated the code to allow setting a display name as well. Now if either field is not provided, we generate both and use the generated value for the missing field. Addressed in: 75277dc

displayName := dbTask.DisplayName
if displayName == "" {
// Fallback for tasks created before display_name column was added.
// Use the prompt as display name, truncated to match display name limits.
Copy link
Member

Choose a reason for hiding this comment

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

If we don't make a change to the logic above, it also applies to tasks created with a predefined name.

Copy link
Contributor

@DanielleMaywood DanielleMaywood left a comment

Choose a reason for hiding this comment

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

I'm happy with this. We also have time before code-freeze/release to address any issues if they pop up

Copy link
Member

@mafredri mafredri left a comment

Choose a reason for hiding this comment

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

I'd like for us to surface generate errors some way, but other than that there are no blockers on my end. Nice work. 👍🏻

@ssncferreira ssncferreira merged commit 3011207 into main Nov 25, 2025
35 checks passed
@ssncferreira ssncferreira deleted the ssncferreira/feat-task-display-name branch November 25, 2025 13:01
@github-actions github-actions bot locked and limited conversation to collaborators Nov 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants