Skip to content

Conversation

@jurgenwerk
Copy link
Contributor

@jurgenwerk jurgenwerk commented Jan 20, 2026

This PR addresses a user experience issue where:

  1. User is in interact mode and opens the AI assistant and tells it to generate something (e.g. "make me a tic tac toe game")
  2. The assistant will switch to code mode and open the index card, then proceed with ai generation and once user accepts the patch to create file(s) nothing happens, they still see the index card.

This PR adds an optional boolean param createFile to switch mode command where it will create the file the assistant is about to generate. The user will be transitioned to code mode, seeing a blank file until the AI assistant is done generating the code.

The changes in this PR alone don't fix the mentioned issue yet - there will be another PR in the skills repo to teach the LLM when to use createFile parameter (I have it almost ready and confirm it works with all of the above).


Note

Introduces optional file creation when switching to code mode and centralized non-conflicting filename handling.

  • Adds createFile to SwitchSubmodeInput and new SwitchSubmodeResult (returns codePath when filename changes)
  • Updates switch-submode to optionally create a blank file via write-text-file when entering "code" from "interact"; updates code path accordingly
  • Enhances write-text-file with useNonConflictingFilename, realm validation, safer existence checks, and returns FileUrlCard
  • Extracts findNonConflictingFilename to utils/file-name and refactors patch-code to use it
  • UI: suppresses result card display for switch-submode* commands in matrix message renderer
  • Adds comprehensive tests for new behaviors and edge cases

Written by Cursor Bugbot for commit 2920284. This will update automatically on new commits. Configure here.

@github-actions
Copy link

Preview deployments

@github-actions
Copy link

github-actions bot commented Jan 20, 2026

Host Test Results

    1 files  ±0      1 suites  ±0   1h 41m 56s ⏱️ -50s
1 912 tests +9  1 895 ✅ +9  17 💤 ±0  0 ❌ ±0 
1 927 runs  +9  1 910 ✅ +9  17 💤 ±0  0 ❌ ±0 

Results for commit 2920284. ± Comparison against base commit 2167921.

♻️ This comment has been updated with latest results.

@jurgenwerk jurgenwerk force-pushed the cs-9640-when-trying-to-create-a-new-card-with-ai-it-will-sometimes branch from 76b1b4d to 2cbf92e Compare January 20, 2026 12:13
@jurgenwerk jurgenwerk requested a review from Copilot January 20, 2026 12:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances the AI assistant's user experience by adding a createFile parameter to the switch-submode command. When switching from interact mode to code mode, the assistant can now create a blank file immediately, allowing users to see an empty file instead of an index card while the AI generates code.

Changes:

  • Added createFile boolean parameter to SwitchSubmodeInput and introduced SwitchSubmodeResult card definition for handling filename conflicts
  • Implemented file creation logic in switch-submode command with automatic conflict resolution when target files already exist
  • Extracted filename conflict resolution logic to a reusable utility function and refactored patch-code command to use it

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/base/command.gts Added createFile field to SwitchSubmodeInput and defined SwitchSubmodeResult card for communicating filename changes
packages/host/app/commands/switch-submode.ts Implemented file creation logic with conflict resolution when switching from interact to code mode
packages/host/app/utils/file-name.ts New utility function for finding non-conflicting filenames
packages/host/app/commands/patch-code.ts Refactored to use shared filename conflict resolution utility
packages/runtime-common/ai/prompt.ts Added instruction generation for AI when filename conflicts occur
packages/host/app/components/matrix/room-message-command.gts Hide result cards for switch-submode commands in the UI
packages/host/tests/integration/commands/switch-submode-test.gts Added tests for file creation and conflict resolution scenarios
packages/ai-bot/tests/prompt-construction-test.ts Added test for AI instruction when filename conflicts occur

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

jurgenwerk and others added 3 commits January 20, 2026 13:56
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jurgenwerk jurgenwerk marked this pull request as ready for review January 20, 2026 13:45
@jurgenwerk jurgenwerk requested a review from a team January 20, 2026 13:57
@jurgenwerk jurgenwerk changed the title Add createFile param to switch submode command Add createFile param to the switch submode command Jan 20, 2026
@jurgenwerk
Copy link
Contributor Author

jurgenwerk commented Jan 21, 2026

Accompanying PR: cardstack/boxel-skills#44

Comment on lines 71 to 83
let { status, content } = await this.cardService.getSource(codeUrl);
if (status === 404) {
await this.cardService.saveSource(codeUrl, '', 'create-file');
} else if (status === 200) {
if (content.trim() !== '') {
let nonConflictingUrl = await findNonConflictingFilename(
codeUrl.href,
(candidateUrl) => this.fileExists(candidateUrl),
);
let newCodeUrl = new URL(nonConflictingUrl);
await this.cardService.saveSource(newCodeUrl, '', 'create-file');
finalCodeUrl = newCodeUrl;

Copy link
Contributor

Choose a reason for hiding this comment

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

It might be elegant to delegate to a separate command to accomplish this.

Copy link
Contributor Author

@jurgenwerk jurgenwerk Jan 23, 2026

Choose a reason for hiding this comment

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

I'll check if I can use WriteTextFileCommand for this

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 adjusted WriteTextFileCommand to fit this case and used it in this command

content = [content, switchSubmodeInstruction]
.filter(Boolean)
.join('\n\n');
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not enthusiastic about having command-specific code in the ai prompt generation. Is this necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My intent was to not add more text to the skills prompt since this should be a rare case. I checked and we can achieve this by adding a line to the development skill and drop this new logic in the ai bot

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ai bot logic removed, and I added some extra instructions in the development skill: cardstack/boxel-skills@2719575#r2721123671

cursor[bot]

This comment was marked as outdated.

@jurgenwerk jurgenwerk force-pushed the cs-9640-when-trying-to-create-a-new-card-with-ai-it-will-sometimes branch from 5084d41 to 8bee425 Compare January 23, 2026 14:39
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

@jurgenwerk jurgenwerk requested a review from lukemelia January 26, 2026 09:47
Comment on lines 131 to +132
@field overwrite = contains(BooleanField);
@field useNonConflictingFilename = contains(BooleanField);
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps it should be an error in the command if the caller passes both overwrite and useNonConflictingFilename as true?

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 idea

@jurgenwerk jurgenwerk merged commit c646a7c into main Jan 26, 2026
94 of 98 checks passed
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