Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 24 additions & 18 deletions src/pieces/core/onboarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,26 @@ def run(self):


class OnboardingCommandStep(BasedOnboardingStep):
def __init__(self, text, predicted_text: str) -> None:
def __init__(self, text, predicted_text: str, prefix_match: bool = False) -> None:
self.text = text
self.predicted_text = predicted_text
self.prefix_match = prefix_match

def _is_valid(self, user_input: str) -> bool:
if self.prefix_match:
s = user_input.strip()
return s.startswith(self.predicted_text) and len(s) > len(self.predicted_text)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

In prefix_match mode, _is_valid requires len(s) > len(self.predicted_text), which rejects pieces ask (no query) even though the CLI supports running ask without args and then prompting for a query. This can still leave users stuck if they try the shorter valid command; consider allowing an exact match as valid (and/or validating based on parsed tokens rather than a raw string prefix).

Suggested change
return s.startswith(self.predicted_text) and len(s) > len(self.predicted_text)
return s.startswith(self.predicted_text) and len(s) >= len(self.predicted_text)

Copilot uses AI. Check for mistakes.
return user_input == self.predicted_text

def run(self):
Settings.logger.print(Markdown(self.text))
# self.click_to_continue(console)

user_input = input(get_prompt()).strip()
while user_input != self.predicted_text:
while not self._is_valid(user_input):
if user_input == "exit":
sys.exit(1)
Settings.logger.print(
Markdown(f"❌ Wrong command. Please use: `{self.predicted_text}`")
)
hint = "e.g. `pieces ask 'your question'`" if self.prefix_match else f"Please use: `{self.predicted_text}`"
Settings.logger.print(Markdown(f"❌ Wrong command. {hint}"))
user_input = input(get_prompt()).strip()

run_command(*extract_text(user_input.removeprefix("pieces ")))
Expand Down Expand Up @@ -200,7 +205,7 @@ def onboarding_command(**kwargs):
"Step 2: Save a Material": [
OnboardingStep(
"Let's get started by saving a material to Pieces.\n"
"Copy the following python material: \n"
"Copy the following Python material:\n"
f"```python\n{demo_snippet}\n```",
create_snippet_one_validation,
),
Expand All @@ -216,18 +221,19 @@ def onboarding_command(**kwargs):
],
"Step 4: Start a Session": [
OnboardingCommandStep(
"Starting a session allows you to run multiple commands without having to start the Pieces CLI every time."
"Starting a session allows you to run multiple commands without having to start the Pieces CLI every time. "
"Start a session with `pieces run`. To exit your session, use `exit`.",
Comment on lines +224 to 225
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

There’s an extra trailing space at the end of the first sentence ("every time. "), which results in an unintended double-space in the rendered onboarding text when concatenated with the next string.

Suggested change
"Starting a session allows you to run multiple commands without having to start the Pieces CLI every time. "
"Start a session with `pieces run`. To exit your session, use `exit`.",
"Starting a session allows you to run multiple commands without having to start the Pieces CLI every time."
" Start a session with `pieces run`. To exit your session, use `exit`.",

Copilot uses AI. Check for mistakes.
"pieces run",
)
],
"Step 5: Chat with the Copilot": [
OnboardingCommandStep(
"Start a chat with the Copilot by using `pieces ask 'How to print I love Pieces CLI in Python and Java'`.",
"pieces ask 'How to print I love Pieces CLI in Python and Java'",
"Start a chat with the Copilot by using `pieces ask 'your question here'`.",
"pieces ask ",
prefix_match=True,
),
OnboardingCommandStep(
"Create a session with Copilot by typing `pieces run` then use `ask` to interact with Copilot.",
"Start a session with Copilot by typing `pieces run`, then use `ask` to interact with Copilot.",
"pieces run",
),
],
Expand All @@ -237,15 +243,15 @@ def onboarding_command(**kwargs):
lambda: (True, ""),
)
],
"Step 7: Sharing your Feedback": [
"Step 7: Share Your Feedback": [
OnboardingCommandStep(
"Your feedback is very **important** to us. Please share some of your feedback by typing `pieces feedback`.",
"Your feedback is very **important** to us. Please share your feedback by typing `pieces feedback`.",
"pieces feedback",
)
],
"Step 8: Contributing": [
OnboardingCommandStep(
"The Pieces CLI is an **open source project** and you can contribute to it by creating a pull request or open an issue by typing `pieces contribute`.",
"The Pieces CLI is an **open source project** and you can contribute to it by creating a pull request or opening an issue with `pieces contribute`.",
"pieces contribute",
)
],
Expand All @@ -263,7 +269,7 @@ def onboarding_command(**kwargs):
)
)

Settings.logger.print("Whenever you want to exit the onboarding flow type `exit`.")
Settings.logger.print("Whenever you want to exit the onboarding flow, type `exit`.")

if not Settings.pieces_client.open_pieces_os():
Settings.logger.print("❌ PiecesOS is not running")
Expand All @@ -276,7 +282,7 @@ def onboarding_command(**kwargs):
"- **Sublime Text**\n"
"- **Visual Studio**\n"
"and web browser extensions for Google Chrome and Firefox and more.\n\n"
"for more information about the integrations check out the **documentation** https://docs.pieces.app/#ides-and-editors. \n\n" # TODO: Add a link to the documentation extensions like the old website
"For more information about the integrations, check out the **documentation** https://docs.pieces.app/#ides-and-editors. \n\n" # TODO: Add a link to the documentation extensions like the old website
"### Key Functionalities\n"
"- Highly contextual generative AI assistant, called **Pieces Copilot**.\n"
"- **Materials Management** for efficient code organization enables you to save and share materials\n"
Expand All @@ -286,7 +292,7 @@ def onboarding_command(**kwargs):
)

OnboardingCommandStep(
"To install PiecesOS run `pieces install`", "pieces install"
"To install PiecesOS, run `pieces install`", "pieces install"
).run()

else:
Expand All @@ -307,7 +313,7 @@ def onboarding_command(**kwargs):
Settings.logger.print(
Markdown("You are now a `10x` more productive developer with Pieces.")
)
Settings.logger.print("For more information visit " + URLs.DOCS_CLI.value)
Settings.logger.print("For more information, visit " + URLs.DOCS_CLI.value)

Settings.user_config.onboarded = True

Expand Down
Loading