✨ feat(prompt): add parent commit options to resolve 409 conflicts#723
✨ feat(prompt): add parent commit options to resolve 409 conflicts#723
Conversation
There was a problem hiding this comment.
Pull request overview
This PR resolves 409 conflicts when updating existing prompts by adding three new CLI options to specify parent commits: --parent-commit, --auto-parent, and --force.
Changes:
- Added
CommitManifestResponsetype to SDK withcommit_hashandmanifestfields - Added
get_commit()method to fetch full commit metadata including hash - Refactored
pull()to useget_commit()internally to reduce code duplication - Added three CLI flags with conflict constraints to handle parent commit scenarios
- Updated test mocks to include
commit_hashfield in responses
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| sdk/src/prompts.rs | Added get_commit() method and CommitManifestResponse type; refactored pull() to use new method |
| sdk/src/lib.rs | Exported CommitManifestResponse in public API |
| cli/src/commands/prompt.rs | Added three parent commit CLI flags with logic to auto-fetch, force push, or use explicit hash |
| sdk/tests/structured_prompts_test.rs | Updated mock responses to include commit_hash field matching new API response structure |
Addressed Copilot Review CommentsComment 1: Test Coverage for get_commit()✅ Fixed - Added dedicated test The test validates:
Comment 2: Make --force Mutually Exclusive✅ Fixed - Updated This prevents ambiguous behavior when Comment 3: Fix repo_exists Logic✅ Fixed - Changed Updated error message to clarify that auto-parent will be disabled when creation fails. All changes committed in cccfda5 |
cccfda5 to
3c54b71
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
cli/src/commands/prompt.rs:647
repo_existsdetection treats any error fromclient.prompts().get(&repo_handle)as “not found” and proceeds tocreate_repo(). This can mis-handle non-404 failures (e.g., auth/scoping problems, transient 5xx), and for--auto-parentit can incorrectly disable parent resolution and then push withoutparent_commit(leading to another 409). Consider matching specifically onLangstarError::ApiError { status: 404, .. }for the create-repo path, and returning the original error for other statuses.
let repo_exists = match client.prompts().get(&repo_handle).await {
Ok(_) => {
println!("✓ Repository exists");
true
}
Err(_) => {
formatter.info(&format!(
"Repository not found, creating {}...",
repo_handle
));
match client
| async fn test_pull_structured_prompt_deserialization_error() { | ||
| let mut server = Server::new_async().await; |
There was a problem hiding this comment.
In test_pull_structured_prompt_deserialization_error, the mocked GET /api/v1/commits response body is missing the required commit_hash field. Since pull() now deserializes into CommitManifestResponse (which requires commit_hash), the test will fail for the wrong reason (missing field) instead of exercising StructuredPrompt manifest deserialization. Update the mock response to include a valid commit_hash while keeping the manifest malformed.
cli/src/commands/prompt.rs
Outdated
| eprintln!("⚠ Warning: Using --force flag"); | ||
| eprintln!(" This will push without parent commit validation"); | ||
| eprintln!(" May overwrite concurrent changes to the prompt"); |
There was a problem hiding this comment.
--force currently just sets final_parent_commit to None, which is the same request behavior as the default (no --parent-commit/--auto-parent). Given the known 409 behavior when updating existing repos without parent_commit, this flag likely won’t do what the help text claims (“push without parent commit validation”). Either implement a real force mechanism supported by the API (if one exists), or rename/reword/remove the flag so it doesn’t promise behavior the request cannot provide.
| eprintln!("⚠ Warning: Using --force flag"); | |
| eprintln!(" This will push without parent commit validation"); | |
| eprintln!(" May overwrite concurrent changes to the prompt"); | |
| eprintln!("⚠ Note: Using --force flag"); | |
| eprintln!(" Parent commit will not be automatically set for this push."); | |
| eprintln!(" This behaves the same as omitting --parent-commit/--auto-parent; the server may still reject updates that require a parent commit."); |
cli/src/commands/prompt.rs
Outdated
| /// Parent commit hash for updates (resolves 409 conflicts) | ||
| #[arg(long, value_name = "HASH", conflicts_with = "auto_parent")] | ||
| parent_commit: Option<String>, | ||
|
|
||
| /// Automatically fetch and use latest commit as parent | ||
| #[arg(long, conflicts_with = "parent_commit")] | ||
| auto_parent: bool, | ||
|
|
||
| /// Force push without parent commit validation (use with caution) | ||
| #[arg(long, conflicts_with_all = ["parent_commit", "auto_parent"])] | ||
| force: bool, |
There was a problem hiding this comment.
New push behavior (--parent-commit, --auto-parent, --force) isn’t covered by existing CLI tests. There are already prompt CLI integration tests in cli/tests/prompt_structured_test.rs, but none exercise updating an existing repo with a second push using --auto-parent (or --parent-commit) to prevent 409s. Adding an integration test that (1) pushes once, (2) pushes again with --auto-parent (and/or explicit --parent-commit from the first response) would protect this new conflict-resolution path.
| pub commit_hash: String, | ||
| /// The commit manifest (prompt template/schema) | ||
| pub manifest: serde_json::Value, | ||
| /// Optional example run IDs |
There was a problem hiding this comment.
The doc comment for examples says “Optional example run IDs”, but the field is Option<Vec<serde_json::Value>> and the LangSmith schema (reference/api-specs/langsmith/prompt-schemas.json) defines examples as an array of RepoExampleResponse objects (not IDs). Update the comment to reflect that these are example run records (or consider introducing a typed RepoExampleResponse struct if you want stronger typing).
| /// Optional example run IDs | |
| /// Optional example run records (serialized RepoExampleResponse objects) |
Adds three new CLI options to `langstar prompt push`: - --parent-commit <HASH>: Specify parent commit explicitly - --auto-parent: Automatically fetch latest commit as parent - --force: Push without parent validation (with warnings) This resolves 409 conflicts when updating existing prompts by providing the parent commit reference that the LangSmith API requires. SDK Changes: - Add CommitManifestResponse type for full commit metadata - Add get_commit() method to fetch commit hash and manifest - Refactor pull() to use get_commit() internally CLI Changes: - Add new flags with conflicts_with constraint - Implement auto-fetch logic for --auto-parent - Add warnings for --force flag - Pass parent_commit to SDK for both regular and structured prompts Tests: - Update mock responses to include commit_hash field - All 609 tests passing Fixes #719 Co-Authored-By: Claude <noreply@anthropic.com>
- Add dedicated test coverage for get_commit() method - Make --force flag mutually exclusive with --parent-commit and --auto-parent - Fix repo_exists logic when repository creation fails All three changes improve code quality and prevent ambiguous behavior. Tests: All 610 tests passing. Co-Authored-By: Claude <noreply@anthropic.com>
Resolves 409 conflicts by automatically fetching latest commit as parent when updating existing prompts, following Git-like UX expectations. Changes: - Remove --parent-commit, --auto-parent, and --force flags - Make parent commit fetching automatic and transparent - New repos: no parent needed (first commit) - Existing repos: auto-fetch latest commit as parent - Graceful error handling with fallback to no parent Fixes #719 Co-Authored-By: Claude <noreply@anthropic.com>
3c54b71 to
e33cd3e
Compare
Summary
Resolves 409 conflicts when updating existing prompts by automatically fetching the latest commit as the parent, following Git-like UX expectations. No flags required - it just works.
Changes
SDK (
sdk/src/prompts.rs,sdk/src/lib.rs)CommitManifestResponsetype withcommit_hashandmanifestfieldsget_commit()method to fetch full commit metadatapull()to useget_commit()internallyCommitManifestResponsein public APICLI (
cli/src/commands/prompt.rs)--parent-commit,--auto-parent, and--forceflags (over-engineered)Tests
Behavior
For new prompts:
For existing prompts:
Error handling (graceful fallback):
Design Decision: Minimal Fix
Issue #719 asked for: "The push should automatically fetch the latest commit hash and use it as the parent commit"
This PR delivers exactly that - no flags, no complexity, just automatic parent fetching like Git.
Why Not Flags?
PR #723 originally added three flags (
--parent-commit,--auto-parent,--force), but this was over-engineered:Future Work (Out of Scope)
The
docs/implementation/ls-prompt-ux-command-redesign.mddesign doc outlines a future CRUD redesign (Phase 2, Issue #668.2) wherepushwill be split intocreateandupdatecommands. This minimal fix:Related Issues
Fixes #719
Test Plan
get_commit()SDK method with proper return type🤖 Generated with Claude Code