rpr-cli 0.3.8__tar.gz → 0.3.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/PKG-INFO +26 -8
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/README.md +24 -6
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/pyproject.toml +9 -2
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/Cargo.lock +1 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/Cargo.toml +1 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/rename.rs +115 -17
- rpr_cli-0.3.11/src/rpr/__init__.py +1 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/catalog.py +18 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/chat_service.py +1 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/checks.py +7 -3
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/prompt_service.py +1 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/shell.py +65 -11
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/checks/base.py +0 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/checks/packages.py +14 -5
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/checks/workspace.py +8 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/cli.py +10 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/check.py +10 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/generate/storybook.py +21 -86
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/generate/ui.py +22 -240
- rpr_cli-0.3.11/src/rpr/commands/generate/web.py +468 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/init.py +61 -57
- rpr_cli-0.3.11/src/rpr/commands/rename.py +452 -0
- rpr_cli-0.3.11/src/rpr/commands/version.py +198 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/dependencies.py +17 -9
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/dependency_manifest_data.py +15 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/base.py +12 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/claude.py +2 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/cursor.py +3 -3
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/github.py +3 -3
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/all.instructions.md +13 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/frontend.instructions.md +19 -2
- rpr_cli-0.3.11/src/rpr/scaffolds/instructions/notebook.instructions.md +10 -0
- rpr_cli-0.3.11/src/rpr/scaffolds/instructions/stories-tracking.instructions.md +12 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/tooling-setup.instructions.md +3 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/templates/registry.py +9 -6
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/ui/prompt_session.py +1 -1
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/ui/theme.py +11 -10
- rpr_cli-0.3.11/src/rpr/workspace.py +303 -0
- rpr_cli-0.3.8/src/rpr/__init__.py +0 -1
- rpr_cli-0.3.8/src/rpr/commands/rename.py +0 -104
- rpr_cli-0.3.8/src/rpr/workspace.py +0 -139
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/LICENSE +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/config/container.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/config/mod.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/config/settings.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/graph.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/lib.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/models/dtos/mod.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/models/entities/mod.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/models/entities/users.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/models/mod.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/parse.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/repos/base.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/repos/mod.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/repos/users.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/resolve.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/rpr-parser/src/walker.rs +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/_native.pyi +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/approval.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/bootstrap.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/client.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/control.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/mock.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/runtime.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/session.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/tools/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/tools/base.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/tools/mutating.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/tools/readonly.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/agent/tools/registry.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/cli_adapter.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/completer.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/conversation_service.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/application/selector.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/checks/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/checks/instructions.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/add.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/chat.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/generate/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/generate/api.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/generate/domain.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/generate/engine.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/map.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/refresh.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/settings.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/sync.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/commands/update.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/context.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/codex.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/copilot.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/generators/gemini.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/manifest_refresh.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/architecture.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/chains.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/classifier.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/coverage.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/dependencies.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/extractor.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/graph.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/output.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/responsibility.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/topology.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/map/walker.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/package_updates.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/project_rename.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/domain/base_entity.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/domain/base_repo.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/domain/container.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/domain/settings.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/api.instructions.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/domain.instructions.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/rust-engine.instructions.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/setup-guide.instructions.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/instructions/tooling.instructions.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/BACKEND_FLOW.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/README.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/client/content.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/client/httpChatStreamClient.spec.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/client/httpChatStreamClient.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/client/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/client/types.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/ChatComposer.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/ChatComposer.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/__screenshots__/ChatComposer.spec.tsx/ChatComposer-renders-custom-action-buttons-beside-the-attachment-control-1.png +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/fileDrop.spec.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/fileDrop.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/ChatComposerMentionTokens.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/ChatSuggestionsPopover.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/LocalFileSuggestionAction.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/localFileSuggestions.spec.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/localFileSuggestions.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/triggerDetection.spec.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/triggerDetection.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/types.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/useChatSuggestions.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/types.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/useChatComposer.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/useChatStream.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/composer/useChatStream.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ChatExperience.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ChatExperience.styles.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ChatExperience.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ChatExperienceComposer.styles.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ChatExperienceComposer.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ChatExperienceHeader.styles.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ChatExperienceHeader.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ThreadHistory.styles.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/ThreadHistory.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/chatStorage.spec.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/chatStorage.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/types.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/useChatExperience.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/experience/useChatExperience.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/testing/createMockChatStreamClient.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/testing/createMockSuggestionProvider.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/testing/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/ChatMessage.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/ChatMessageActions.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/ChatMessageContent.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/ChatMessageContent.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/ChatThread.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/ChatThread.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/README.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/contentFormat.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/streaming.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/thread/types.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponent.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponent.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponentList.spec.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponentList.tsx +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/chat/virtual-list/index.ts +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/fetch.service.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/sticky-navigation.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/sticky-navigation.spec.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/js_special_files/vitest-browser-config.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/api/routes/chat_routes.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/api/tests/test_chat.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/models/dtos/chat_dtos.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/models/dtos/conversation_history_dtos.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/models/entities/conversation_history.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/repos/conversation_history.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/agent_session_codec.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/chat_service.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/conversation_history_service.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/conversation_operations.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/history_codec.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/in_memory_history_store.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/postgres_history_store.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/protocols/conversation_history_store.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/protocols/conversation_runtime.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/services/protocols/llm_provider.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/tests/test_chat_dtos.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/tests/test_chat_service.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/tests/test_history_codec.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/tests/test_history_projection.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/tests/test_persistence_config.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/chat/domain/tests/test_postgres_history_store.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/models/dtos/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/models/dtos/vllm_model_dtos.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/agents/VLLM_SETUP.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/agents/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/agents/model_catalog.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/agents/vllm_agent_factory.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/agents/vllm_agent_factory_protocol.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/agents/vllm_inference_coordinator.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/runtimes/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/runtimes/agents_sdk.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/services/runtimes/agents_sdk_message_mapping.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/tests/test_agents_sdk_runtime.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/tests/test_vllm_model_catalog.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/py_special_files/vllm_provider/domain/tests/test_vllm_provider.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/camel_case_model.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/domain_container.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/domain_settings.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/dto_util.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/encrypted_column.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/logging.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/mapper_util.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/partial_update.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/scaffolds/special_files/test_encrypted_column.md +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/templates/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/ui/__init__.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/ui/console.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/ui/markdown.py +0 -0
- {rpr_cli-0.3.8 → rpr_cli-0.3.11}/src/rpr/ui/renderers.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rpr-cli
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Requires-Dist: typer>=0.24.1
|
|
3
|
+
Version: 0.3.11
|
|
4
|
+
Requires-Dist: typer>=0.24.1,<0.26
|
|
5
5
|
Requires-Dist: jinja2>=3.1.5
|
|
6
6
|
Requires-Dist: pyyaml>=6.0.2
|
|
7
7
|
Requires-Dist: rich>=14.3.3
|
|
@@ -70,6 +70,7 @@ cd my-app
|
|
|
70
70
|
rpr generate domain my-app # Add a Python domain package
|
|
71
71
|
rpr generate api my-app # Add a FastAPI application
|
|
72
72
|
rpr generate ui my-app # Add a React UI library and web app
|
|
73
|
+
rpr generate web landing # Add another web app; asks whether to depend on the UI library
|
|
73
74
|
rpr generate engine my-app # Add a Rust/PyO3 computation engine
|
|
74
75
|
rpr generate storybook # Add Storybook for UI component development
|
|
75
76
|
rpr rename new-app # Rename the workspace identity and references
|
|
@@ -87,6 +88,19 @@ source and experiments to remain in rename scope. Binary contents, VCS data, and
|
|
|
87
88
|
symlink targets are never changed. The outer workspace directory keeps its
|
|
88
89
|
existing name.
|
|
89
90
|
|
|
91
|
+
After applying the rename, RPR synchronizes Node and Python dependencies and
|
|
92
|
+
runs uncached Nx build, Rust-engine build, and typecheck targets with the Nx
|
|
93
|
+
daemon disabled. This verifies the renamed project graph and commands without
|
|
94
|
+
deleting the existing Nx cache. Pass `--skip-verify` to omit these checks; a
|
|
95
|
+
dry run previews them without executing anything. If verification fails, the
|
|
96
|
+
rename remains applied and RPR prints the command to retry.
|
|
97
|
+
|
|
98
|
+
The success output includes a guarded command for optionally renaming the outer
|
|
99
|
+
workspace directory. Git remotes and hosted repository names are never changed.
|
|
100
|
+
When a hosted repository still matches the old project name, rename it through
|
|
101
|
+
the hosting provider if desired and then update its local URL with
|
|
102
|
+
`git remote set-url`. Local and remote branch names are unaffected.
|
|
103
|
+
|
|
90
104
|
`rpr init <project-name>` creates the project directory when it does not exist. If the directory already exists and is not an NX workspace, RPR initializes Git and runs `nx init` inside that directory.
|
|
91
105
|
|
|
92
106
|
By default, `rpr init` scaffolds the root workspace and AI instructions only. To create project components during initialization, repeat `--scaffold` or pass a comma-separated list:
|
|
@@ -111,14 +125,16 @@ Available scaffolds are:
|
|
|
111
125
|
|
|
112
126
|
### Dependency Placement
|
|
113
127
|
|
|
114
|
-
RPR keeps dependencies close to the package that uses them.
|
|
128
|
+
RPR keeps Python dependencies close to the package that uses them and Node dependencies at the workspace root.
|
|
115
129
|
|
|
116
130
|
- Root Python tooling such as Ruff, pytest, pyright, pre-commit, and maturin lives in the root `pyproject.toml`.
|
|
117
131
|
- Domain runtime dependencies such as `sqlmodel`, `asyncpg`, `pydantic-settings`, and optional `alembic` are added to `packages/python/domain/pyproject.toml`.
|
|
118
132
|
- API runtime dependencies such as `fastapi`, `uvicorn`, and the workspace domain package are added to `apps/<name>-api/pyproject.toml`.
|
|
119
|
-
- Node dependencies are
|
|
133
|
+
- Node dependencies are declared and installed only in the root `package.json`, so every app and package shares one version of each. Package-level `package.json` files carry metadata and workspace links such as `@my-app/ui`. Generators install only the dependencies the root does not already declare, so adding another app never bumps existing versions.
|
|
134
|
+
|
|
135
|
+
`rpr generate web <name>` adds another web app (for example a landing page) at `apps/<name>-web`. When a UI library exists it asks whether to add the library as a dependency (`--link-ui` / `--no-link-ui` skip the prompt); linked apps get a starter page in the library's `src/pages/`, and unlinked apps are fully standalone. Each web app gets its own dev-server port (3000, 3001, ...), so `npx nx serve <name>-web` runs alongside the others. The generated workspace requires Node 24 LTS or newer.
|
|
120
136
|
|
|
121
|
-
Python dependency changes are made with `uv` so they are tracked in `pyproject.toml`. Node dependency changes are made
|
|
137
|
+
Python dependency changes are made with `uv` so they are tracked in `pyproject.toml`. Node dependency changes are made from the root with `npm install`.
|
|
122
138
|
|
|
123
139
|
Update project-owned package manifests from upstream registries with `rpr update node` or `rpr update python`. Node updates target `package.json`; Python updates target `pyproject.toml` by default and fall back to `requirements.txt` when no `pyproject.toml` exists. Use `--file` to update a nested manifest, `--dry-run` to preview without changing files or running installers, and `--include-major` to opt into major-version updates.
|
|
124
140
|
|
|
@@ -271,9 +287,11 @@ No `PYPI_API_TOKEN` secret is required when publishing through GitHub Actions OI
|
|
|
271
287
|
Release flow:
|
|
272
288
|
|
|
273
289
|
```bash
|
|
274
|
-
#
|
|
275
|
-
|
|
276
|
-
git
|
|
290
|
+
rpr version bump patch # updates Python, Cargo.toml, and Cargo.lock
|
|
291
|
+
# Or repair/set an explicit version: rpr version set 0.3.9
|
|
292
|
+
git add src/rpr/__init__.py rpr-parser/Cargo.toml rpr-parser/Cargo.lock
|
|
293
|
+
git commit -m "Release 0.3.9"
|
|
294
|
+
git tag v0.3.9
|
|
277
295
|
git push origin main --tags
|
|
278
296
|
```
|
|
279
297
|
|
|
@@ -53,6 +53,7 @@ cd my-app
|
|
|
53
53
|
rpr generate domain my-app # Add a Python domain package
|
|
54
54
|
rpr generate api my-app # Add a FastAPI application
|
|
55
55
|
rpr generate ui my-app # Add a React UI library and web app
|
|
56
|
+
rpr generate web landing # Add another web app; asks whether to depend on the UI library
|
|
56
57
|
rpr generate engine my-app # Add a Rust/PyO3 computation engine
|
|
57
58
|
rpr generate storybook # Add Storybook for UI component development
|
|
58
59
|
rpr rename new-app # Rename the workspace identity and references
|
|
@@ -70,6 +71,19 @@ source and experiments to remain in rename scope. Binary contents, VCS data, and
|
|
|
70
71
|
symlink targets are never changed. The outer workspace directory keeps its
|
|
71
72
|
existing name.
|
|
72
73
|
|
|
74
|
+
After applying the rename, RPR synchronizes Node and Python dependencies and
|
|
75
|
+
runs uncached Nx build, Rust-engine build, and typecheck targets with the Nx
|
|
76
|
+
daemon disabled. This verifies the renamed project graph and commands without
|
|
77
|
+
deleting the existing Nx cache. Pass `--skip-verify` to omit these checks; a
|
|
78
|
+
dry run previews them without executing anything. If verification fails, the
|
|
79
|
+
rename remains applied and RPR prints the command to retry.
|
|
80
|
+
|
|
81
|
+
The success output includes a guarded command for optionally renaming the outer
|
|
82
|
+
workspace directory. Git remotes and hosted repository names are never changed.
|
|
83
|
+
When a hosted repository still matches the old project name, rename it through
|
|
84
|
+
the hosting provider if desired and then update its local URL with
|
|
85
|
+
`git remote set-url`. Local and remote branch names are unaffected.
|
|
86
|
+
|
|
73
87
|
`rpr init <project-name>` creates the project directory when it does not exist. If the directory already exists and is not an NX workspace, RPR initializes Git and runs `nx init` inside that directory.
|
|
74
88
|
|
|
75
89
|
By default, `rpr init` scaffolds the root workspace and AI instructions only. To create project components during initialization, repeat `--scaffold` or pass a comma-separated list:
|
|
@@ -94,14 +108,16 @@ Available scaffolds are:
|
|
|
94
108
|
|
|
95
109
|
### Dependency Placement
|
|
96
110
|
|
|
97
|
-
RPR keeps dependencies close to the package that uses them.
|
|
111
|
+
RPR keeps Python dependencies close to the package that uses them and Node dependencies at the workspace root.
|
|
98
112
|
|
|
99
113
|
- Root Python tooling such as Ruff, pytest, pyright, pre-commit, and maturin lives in the root `pyproject.toml`.
|
|
100
114
|
- Domain runtime dependencies such as `sqlmodel`, `asyncpg`, `pydantic-settings`, and optional `alembic` are added to `packages/python/domain/pyproject.toml`.
|
|
101
115
|
- API runtime dependencies such as `fastapi`, `uvicorn`, and the workspace domain package are added to `apps/<name>-api/pyproject.toml`.
|
|
102
|
-
- Node dependencies are
|
|
116
|
+
- Node dependencies are declared and installed only in the root `package.json`, so every app and package shares one version of each. Package-level `package.json` files carry metadata and workspace links such as `@my-app/ui`. Generators install only the dependencies the root does not already declare, so adding another app never bumps existing versions.
|
|
117
|
+
|
|
118
|
+
`rpr generate web <name>` adds another web app (for example a landing page) at `apps/<name>-web`. When a UI library exists it asks whether to add the library as a dependency (`--link-ui` / `--no-link-ui` skip the prompt); linked apps get a starter page in the library's `src/pages/`, and unlinked apps are fully standalone. Each web app gets its own dev-server port (3000, 3001, ...), so `npx nx serve <name>-web` runs alongside the others. The generated workspace requires Node 24 LTS or newer.
|
|
103
119
|
|
|
104
|
-
Python dependency changes are made with `uv` so they are tracked in `pyproject.toml`. Node dependency changes are made
|
|
120
|
+
Python dependency changes are made with `uv` so they are tracked in `pyproject.toml`. Node dependency changes are made from the root with `npm install`.
|
|
105
121
|
|
|
106
122
|
Update project-owned package manifests from upstream registries with `rpr update node` or `rpr update python`. Node updates target `package.json`; Python updates target `pyproject.toml` by default and fall back to `requirements.txt` when no `pyproject.toml` exists. Use `--file` to update a nested manifest, `--dry-run` to preview without changing files or running installers, and `--include-major` to opt into major-version updates.
|
|
107
123
|
|
|
@@ -254,9 +270,11 @@ No `PYPI_API_TOKEN` secret is required when publishing through GitHub Actions OI
|
|
|
254
270
|
Release flow:
|
|
255
271
|
|
|
256
272
|
```bash
|
|
257
|
-
#
|
|
258
|
-
|
|
259
|
-
git
|
|
273
|
+
rpr version bump patch # updates Python, Cargo.toml, and Cargo.lock
|
|
274
|
+
# Or repair/set an explicit version: rpr version set 0.3.9
|
|
275
|
+
git add src/rpr/__init__.py rpr-parser/Cargo.toml rpr-parser/Cargo.lock
|
|
276
|
+
git commit -m "Release 0.3.9"
|
|
277
|
+
git tag v0.3.9
|
|
260
278
|
git push origin main --tags
|
|
261
279
|
```
|
|
262
280
|
|
|
@@ -6,7 +6,7 @@ readme = "README.md"
|
|
|
6
6
|
license = "MIT"
|
|
7
7
|
requires-python = ">=3.14"
|
|
8
8
|
dependencies = [
|
|
9
|
-
"typer>=0.24.1",
|
|
9
|
+
"typer>=0.24.1,<0.26",
|
|
10
10
|
"jinja2>=3.1.5",
|
|
11
11
|
"pyyaml>=6.0.2",
|
|
12
12
|
"rich>=14.3.3",
|
|
@@ -20,7 +20,7 @@ dependencies = [
|
|
|
20
20
|
rpr = "rpr.cli:app"
|
|
21
21
|
|
|
22
22
|
[dependency-groups]
|
|
23
|
-
dev = ["pytest>=9.0.2", "maturin>=1.
|
|
23
|
+
dev = ["pytest>=9.0.2", "maturin>=1.12.6,<2.0", "ruff>=0.15"]
|
|
24
24
|
|
|
25
25
|
[build-system]
|
|
26
26
|
requires = ["maturin>=1.12.6,<2.0"]
|
|
@@ -35,3 +35,10 @@ include = [{ path = "LICENSE", format = "sdist" }]
|
|
|
35
35
|
|
|
36
36
|
[tool.pytest.ini_options]
|
|
37
37
|
testpaths = ["tests"]
|
|
38
|
+
|
|
39
|
+
[tool.ruff]
|
|
40
|
+
# The scaffolds are templates (many are not valid Python/TS until rendered).
|
|
41
|
+
extend-exclude = ["src/rpr/scaffolds", "rpr-parser/target"]
|
|
42
|
+
|
|
43
|
+
[tool.ruff.lint]
|
|
44
|
+
select = ["E4", "E7", "E9", "F"]
|
|
@@ -158,16 +158,27 @@ impl Replacer {
|
|
|
158
158
|
let mut position = 0;
|
|
159
159
|
let mut replacements = 0;
|
|
160
160
|
while position < text.len() {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
161
|
+
let new_match = self.match_new(text, position);
|
|
162
|
+
let old_match = self.match_old(text, position);
|
|
163
|
+
match (old_match, new_match) {
|
|
164
|
+
(Some((old, new)), Some(existing)) if old.len() > existing.len() => {
|
|
165
|
+
output.push_str(new);
|
|
166
|
+
position += old.len();
|
|
167
|
+
replacements += 1;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
(_, Some(existing)) => {
|
|
171
|
+
output.push_str(existing);
|
|
172
|
+
position += existing.len();
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
(Some((old, new)), None) => {
|
|
176
|
+
output.push_str(new);
|
|
177
|
+
position += old.len();
|
|
178
|
+
replacements += 1;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
(None, None) => {}
|
|
171
182
|
}
|
|
172
183
|
let ch = text[position..]
|
|
173
184
|
.chars()
|
|
@@ -182,12 +193,16 @@ impl Replacer {
|
|
|
182
193
|
fn has_stale_reference(&self, text: &str) -> bool {
|
|
183
194
|
let mut position = 0;
|
|
184
195
|
while position < text.len() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
let new_match = self.match_new(text, position);
|
|
197
|
+
let old_match = self.match_old(text, position);
|
|
198
|
+
match (old_match, new_match) {
|
|
199
|
+
(Some((old, _)), Some(existing)) if old.len() > existing.len() => return true,
|
|
200
|
+
(_, Some(existing)) => {
|
|
201
|
+
position += existing.len();
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
(Some(_), None) => return true,
|
|
205
|
+
(None, None) => {}
|
|
191
206
|
}
|
|
192
207
|
position += text[position..].chars().next().unwrap().len_utf8();
|
|
193
208
|
}
|
|
@@ -288,6 +303,7 @@ pub fn plan(root: PathBuf, new_name: String) -> Result<NativeRenamePlan, String>
|
|
|
288
303
|
validate_new_name(&old_name, &new_name)?;
|
|
289
304
|
let replacer = Replacer::new(build_replacements(&old_name, &new_name, variables));
|
|
290
305
|
let (entries, mut skipped) = walk_workspace(&root)?;
|
|
306
|
+
validate_unicode_paths(&root, &entries, &skipped)?;
|
|
291
307
|
let files: Vec<_> = entries
|
|
292
308
|
.iter()
|
|
293
309
|
.filter(|entry| entry.is_file())
|
|
@@ -653,11 +669,37 @@ fn build_path_moves(
|
|
|
653
669
|
fn rename_relative_path(path: &Path, replacer: &Replacer) -> PathBuf {
|
|
654
670
|
let mut output = PathBuf::new();
|
|
655
671
|
for component in path.components() {
|
|
656
|
-
|
|
672
|
+
let component = component
|
|
673
|
+
.as_os_str()
|
|
674
|
+
.to_str()
|
|
675
|
+
.expect("workspace paths were validated as Unicode");
|
|
676
|
+
output.push(replacer.replace(component).0);
|
|
657
677
|
}
|
|
658
678
|
output
|
|
659
679
|
}
|
|
660
680
|
|
|
681
|
+
fn validate_unicode_paths(
|
|
682
|
+
root: &Path,
|
|
683
|
+
entries: &[PathBuf],
|
|
684
|
+
skipped: &[SkippedPath],
|
|
685
|
+
) -> Result<(), String> {
|
|
686
|
+
for entry in entries.iter().chain(skipped.iter().map(|item| &item.path)) {
|
|
687
|
+
let relative = entry
|
|
688
|
+
.strip_prefix(root)
|
|
689
|
+
.expect("walked path is beneath root");
|
|
690
|
+
if relative
|
|
691
|
+
.components()
|
|
692
|
+
.any(|component| component.as_os_str().to_str().is_none())
|
|
693
|
+
{
|
|
694
|
+
return Err(format!(
|
|
695
|
+
"Workspace path is not valid Unicode and cannot be renamed safely: {:?}",
|
|
696
|
+
entry.as_os_str()
|
|
697
|
+
));
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
Ok(())
|
|
701
|
+
}
|
|
702
|
+
|
|
661
703
|
fn update_config(text: &str, new_name: &str) -> Result<(String, usize), String> {
|
|
662
704
|
let mut config: Value = serde_yaml::from_str(text)
|
|
663
705
|
.map_err(|error| format!("Renamed .rpr.yaml would be invalid: {error}"))?;
|
|
@@ -1005,6 +1047,28 @@ mod tests {
|
|
|
1005
1047
|
assert_eq!(count, 1);
|
|
1006
1048
|
}
|
|
1007
1049
|
|
|
1050
|
+
#[test]
|
|
1051
|
+
fn longest_token_wins_for_shortening_and_expansion() {
|
|
1052
|
+
let shortening = Replacer::new(HashMap::from([
|
|
1053
|
+
("foo-bar".into(), "foo".into()),
|
|
1054
|
+
("foo_bar".into(), "foo".into()),
|
|
1055
|
+
("FooBar".into(), "Foo".into()),
|
|
1056
|
+
]));
|
|
1057
|
+
let (output, count) =
|
|
1058
|
+
shortening.replace("nx serve foo-bar-web; from foo_bar_domain import FooBarService");
|
|
1059
|
+
assert_eq!(
|
|
1060
|
+
output,
|
|
1061
|
+
"nx serve foo-web; from foo_domain import FooService"
|
|
1062
|
+
);
|
|
1063
|
+
assert_eq!(count, 3);
|
|
1064
|
+
assert!(!shortening.has_stale_reference(&output));
|
|
1065
|
+
|
|
1066
|
+
let expansion = Replacer::new(HashMap::from([("foo".into(), "foo-bar".into())]));
|
|
1067
|
+
let (output, count) = expansion.replace("foo foo-bar");
|
|
1068
|
+
assert_eq!(output, "foo-bar foo-bar");
|
|
1069
|
+
assert_eq!(count, 1);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1008
1072
|
#[test]
|
|
1009
1073
|
fn bootstrap_defaults_cover_named_virtual_environments() {
|
|
1010
1074
|
let temp = tempfile::tempdir().unwrap();
|
|
@@ -1046,6 +1110,40 @@ mod tests {
|
|
|
1046
1110
|
.contains("new_app_domain"));
|
|
1047
1111
|
}
|
|
1048
1112
|
|
|
1113
|
+
#[test]
|
|
1114
|
+
fn shortening_rename_updates_nested_paths_and_references() {
|
|
1115
|
+
let temp = workspace();
|
|
1116
|
+
let plan = plan(temp.path().to_path_buf(), "my".into()).unwrap();
|
|
1117
|
+
|
|
1118
|
+
apply(&plan).unwrap();
|
|
1119
|
+
|
|
1120
|
+
let renamed = temp
|
|
1121
|
+
.path()
|
|
1122
|
+
.join("packages/python/my_domain/src/my_domain/main.py");
|
|
1123
|
+
assert!(renamed.is_file());
|
|
1124
|
+
assert!(fs::read_to_string(renamed).unwrap().contains("my_domain"));
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
#[cfg(unix)]
|
|
1128
|
+
#[test]
|
|
1129
|
+
fn non_unicode_workspace_path_aborts_planning() {
|
|
1130
|
+
use std::ffi::OsString;
|
|
1131
|
+
use std::os::unix::ffi::OsStringExt;
|
|
1132
|
+
|
|
1133
|
+
let temp = workspace();
|
|
1134
|
+
let invalid = temp
|
|
1135
|
+
.path()
|
|
1136
|
+
.join(OsString::from_vec(b"my-app-\xff.txt".to_vec()));
|
|
1137
|
+
write(&invalid, b"my-app\n");
|
|
1138
|
+
|
|
1139
|
+
let error = plan(temp.path().to_path_buf(), "new-app".into())
|
|
1140
|
+
.err()
|
|
1141
|
+
.expect("non-Unicode path should fail planning");
|
|
1142
|
+
|
|
1143
|
+
assert!(error.contains("not valid Unicode"));
|
|
1144
|
+
assert!(temp.path().join("packages/python/my_app_domain").is_dir());
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1049
1147
|
#[test]
|
|
1050
1148
|
fn ignored_virtual_environment_is_never_planned_or_validated() {
|
|
1051
1149
|
let temp = workspace();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.11"
|
|
@@ -188,6 +188,23 @@ COMMAND_CATALOG: tuple[CommandDefinition, ...] = (
|
|
|
188
188
|
),
|
|
189
189
|
),
|
|
190
190
|
),
|
|
191
|
+
CommandDefinition(
|
|
192
|
+
name="web",
|
|
193
|
+
description="Generate a web app.",
|
|
194
|
+
action_id="generate.web",
|
|
195
|
+
arguments=(CommandArgument("name", "App name."),),
|
|
196
|
+
options=(
|
|
197
|
+
CommandOption(
|
|
198
|
+
"--ui-package",
|
|
199
|
+
"Target UI package.",
|
|
200
|
+
kind="value",
|
|
201
|
+
value_name="PACKAGE",
|
|
202
|
+
),
|
|
203
|
+
CommandOption(
|
|
204
|
+
"--dry-run", "Preview changes without writing.", kind="flag"
|
|
205
|
+
),
|
|
206
|
+
),
|
|
207
|
+
),
|
|
191
208
|
CommandDefinition(
|
|
192
209
|
name="engine",
|
|
193
210
|
description="Generate a Rust engine package.",
|
|
@@ -462,7 +479,7 @@ def usage_string(cmd: CommandDefinition) -> str:
|
|
|
462
479
|
|
|
463
480
|
Group commands show pipe-separated child names::
|
|
464
481
|
|
|
465
|
-
/generate <domain|api|ui|engine|storybook>
|
|
482
|
+
/generate <domain|api|ui|web|engine|storybook>
|
|
466
483
|
|
|
467
484
|
Leaf commands show arguments and options::
|
|
468
485
|
|
|
@@ -26,7 +26,7 @@ from rpr.application.completer import (
|
|
|
26
26
|
from rpr.application.prompt_service import PromptService
|
|
27
27
|
from rpr.application.shell import CommandShellService, ShellPresenter
|
|
28
28
|
from rpr.context import RunContext
|
|
29
|
-
from rpr.ui.console import
|
|
29
|
+
from rpr.ui.console import refresh_console
|
|
30
30
|
from rpr.ui.renderers import (
|
|
31
31
|
render_approval_prompt,
|
|
32
32
|
render_chat_hint,
|
|
@@ -3,16 +3,20 @@ from __future__ import annotations
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
from rpr.checks.base import CheckResult
|
|
6
7
|
from rpr.checks.instructions import check_instructions
|
|
7
8
|
from rpr.checks.packages import check_packages
|
|
8
9
|
from rpr.checks.workspace import check_workspace
|
|
9
10
|
from rpr.generators.base import SyncConfig
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
CHECK_GROUPS = ("workspace", "instructions", "packages")
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
@dataclass(slots=True, frozen=True)
|
|
13
17
|
class CheckReport:
|
|
14
18
|
project_name: str
|
|
15
|
-
results: list[
|
|
19
|
+
results: list[CheckResult]
|
|
16
20
|
|
|
17
21
|
|
|
18
22
|
def collect_check_report(project_dir: Path, group: str | None = None) -> CheckReport:
|
|
@@ -22,7 +26,7 @@ def collect_check_report(project_dir: Path, group: str | None = None) -> CheckRe
|
|
|
22
26
|
variables = config.variables or {}
|
|
23
27
|
project_name = variables.get("name", "(unknown)")
|
|
24
28
|
requested_group = None if group is None else group.lower()
|
|
25
|
-
results: list[
|
|
29
|
+
results: list[CheckResult] = []
|
|
26
30
|
|
|
27
31
|
if requested_group in {None, "workspace"}:
|
|
28
32
|
results.extend(check_workspace(project_dir))
|
|
@@ -36,7 +40,7 @@ def collect_check_report(project_dir: Path, group: str | None = None) -> CheckRe
|
|
|
36
40
|
return CheckReport(project_name=project_name, results=results)
|
|
37
41
|
|
|
38
42
|
|
|
39
|
-
def serialize_check_results(results: list[
|
|
43
|
+
def serialize_check_results(results: list[CheckResult]) -> list[dict[str, object]]:
|
|
40
44
|
return [
|
|
41
45
|
{
|
|
42
46
|
"group": result.group,
|
|
@@ -12,7 +12,7 @@ from rpr.agent.session import ChatSession
|
|
|
12
12
|
from rpr.application.conversation_service import (
|
|
13
13
|
ConversationService,
|
|
14
14
|
ConversationSummary,
|
|
15
|
-
InMemoryConversationRepository,
|
|
15
|
+
InMemoryConversationRepository, # noqa: F401 (re-exported)
|
|
16
16
|
)
|
|
17
17
|
from rpr.ui.prompt_session import PromptSessionAdapter
|
|
18
18
|
|
|
@@ -6,6 +6,7 @@ from dataclasses import dataclass
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import ClassVar, Protocol
|
|
8
8
|
|
|
9
|
+
import click
|
|
9
10
|
import typer
|
|
10
11
|
|
|
11
12
|
from rpr.agent.bootstrap import ChatRuntimeBundle
|
|
@@ -287,6 +288,7 @@ class CommandShellService:
|
|
|
287
288
|
self._active_presenter.info(f"Running /init for {project_name}.")
|
|
288
289
|
exit_code = self._invoke_command(
|
|
289
290
|
init_command.init,
|
|
291
|
+
typer.Context(click.Command("init")),
|
|
290
292
|
project_name=project_name,
|
|
291
293
|
dry_run=namespace.dry_run,
|
|
292
294
|
python_version=namespace.python,
|
|
@@ -301,6 +303,9 @@ class CommandShellService:
|
|
|
301
303
|
from rpr.commands.generate import engine as generate_engine_command
|
|
302
304
|
from rpr.commands.generate import storybook as generate_storybook_command
|
|
303
305
|
from rpr.commands.generate import ui as generate_ui_command
|
|
306
|
+
from rpr.commands.generate import web as generate_web_command
|
|
307
|
+
from rpr.dependencies import node_project_name, ui_package_name
|
|
308
|
+
from rpr.workspace import find_ui_packages
|
|
304
309
|
|
|
305
310
|
parser = ShellArgumentParser(prog="/generate", add_help=False)
|
|
306
311
|
subparsers = parser.add_subparsers(dest="target")
|
|
@@ -314,11 +319,21 @@ class CommandShellService:
|
|
|
314
319
|
storybook_parser.add_argument("--dry-run", action="store_true")
|
|
315
320
|
storybook_parser.add_argument("--ui-package")
|
|
316
321
|
|
|
322
|
+
web_parser = subparsers.add_parser("web", add_help=False)
|
|
323
|
+
web_parser.add_argument("name", nargs="?")
|
|
324
|
+
web_parser.add_argument("--dry-run", action="store_true")
|
|
325
|
+
web_parser.add_argument("--ui-package")
|
|
326
|
+
web_parser.add_argument(
|
|
327
|
+
"--link-ui", action=argparse.BooleanOptionalAction, default=None
|
|
328
|
+
)
|
|
329
|
+
|
|
317
330
|
namespace = self._parse_args(parser, parsed.args)
|
|
318
331
|
if namespace is None:
|
|
319
332
|
return True
|
|
320
333
|
if namespace.target is None:
|
|
321
|
-
raise ValueError(
|
|
334
|
+
raise ValueError(
|
|
335
|
+
"Usage: /generate <domain|api|ui|web|engine|storybook> ..."
|
|
336
|
+
)
|
|
322
337
|
|
|
323
338
|
if namespace.target == "domain":
|
|
324
339
|
name = namespace.name or await self._active_prompts.prompt("App name")
|
|
@@ -345,11 +360,43 @@ class CommandShellService:
|
|
|
345
360
|
)
|
|
346
361
|
return True
|
|
347
362
|
|
|
363
|
+
if namespace.target == "web":
|
|
364
|
+
name = namespace.name or await self._active_prompts.prompt("App name")
|
|
365
|
+
ui_package = namespace.ui_package
|
|
366
|
+
link_ui = namespace.link_ui
|
|
367
|
+
ui_packages = find_ui_packages(self._bundle.ctx.project_dir)
|
|
368
|
+
if ui_packages and not ui_package:
|
|
369
|
+
ui_package = ui_packages[0]
|
|
370
|
+
if len(ui_packages) > 1:
|
|
371
|
+
self._active_presenter.table(
|
|
372
|
+
"Web App Targets",
|
|
373
|
+
["Package"],
|
|
374
|
+
[[package] for package in ui_packages],
|
|
375
|
+
)
|
|
376
|
+
ui_package = (
|
|
377
|
+
await self._active_prompts.prompt(
|
|
378
|
+
"UI package", default=ui_packages[0]
|
|
379
|
+
)
|
|
380
|
+
).strip() or ui_packages[0]
|
|
381
|
+
if ui_package and link_ui is None:
|
|
382
|
+
answer = await self._active_prompts.prompt(
|
|
383
|
+
f"Add {ui_package_name(ui_package)} as a dependency of "
|
|
384
|
+
f"{node_project_name(name, 'web')}? (Y/n)",
|
|
385
|
+
default="y",
|
|
386
|
+
)
|
|
387
|
+
link_ui = answer.strip().lower() not in {"n", "no"}
|
|
388
|
+
self._invoke_command(
|
|
389
|
+
generate_web_command.web,
|
|
390
|
+
name=name,
|
|
391
|
+
ui_package=ui_package,
|
|
392
|
+
link_ui=link_ui,
|
|
393
|
+
dry_run=namespace.dry_run,
|
|
394
|
+
)
|
|
395
|
+
return True
|
|
396
|
+
|
|
348
397
|
ui_package = namespace.ui_package
|
|
349
398
|
if not ui_package:
|
|
350
|
-
ui_packages =
|
|
351
|
-
self._bundle.ctx.project_dir
|
|
352
|
-
)
|
|
399
|
+
ui_packages = find_ui_packages(self._bundle.ctx.project_dir)
|
|
353
400
|
if len(ui_packages) == 1:
|
|
354
401
|
ui_package = ui_packages[0]
|
|
355
402
|
elif len(ui_packages) > 1:
|
|
@@ -376,7 +423,7 @@ class CommandShellService:
|
|
|
376
423
|
|
|
377
424
|
parser = ShellArgumentParser(prog="/sync", add_help=False)
|
|
378
425
|
parser.add_argument("action", nargs="?", default="rules")
|
|
379
|
-
parser.add_argument("--target")
|
|
426
|
+
parser.add_argument("--target", action="append")
|
|
380
427
|
parser.add_argument("--dry-run", action="store_true")
|
|
381
428
|
namespace = self._parse_args(parser, parsed.args)
|
|
382
429
|
if namespace is None:
|
|
@@ -385,7 +432,9 @@ class CommandShellService:
|
|
|
385
432
|
raise ValueError("Usage: /sync [rules] [--target cursor] [--dry-run]")
|
|
386
433
|
|
|
387
434
|
self._invoke_command(
|
|
388
|
-
sync_command.rules,
|
|
435
|
+
sync_command.rules,
|
|
436
|
+
target=namespace.target or [],
|
|
437
|
+
dry_run=namespace.dry_run,
|
|
389
438
|
)
|
|
390
439
|
return True
|
|
391
440
|
|
|
@@ -395,6 +444,7 @@ class CommandShellService:
|
|
|
395
444
|
parser = ShellArgumentParser(prog="/add", add_help=False)
|
|
396
445
|
parser.add_argument("action", nargs="?", default="template")
|
|
397
446
|
parser.add_argument("template_id", nargs="?")
|
|
447
|
+
parser.add_argument("template_name", nargs="?")
|
|
398
448
|
parser.add_argument("--list", action="store_true")
|
|
399
449
|
parser.add_argument("--force", action="store_true")
|
|
400
450
|
parser.add_argument("--name")
|
|
@@ -405,16 +455,20 @@ class CommandShellService:
|
|
|
405
455
|
return True
|
|
406
456
|
if namespace.action != "template":
|
|
407
457
|
raise ValueError(
|
|
408
|
-
"Usage: /add template <template-id>
|
|
458
|
+
"Usage: /add template [node|python] <template-id> "
|
|
459
|
+
"[--name app] [--force] [--dry-run]"
|
|
409
460
|
)
|
|
410
461
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
462
|
+
# `/add template [lang] <id>`: the command takes the language (or the id,
|
|
463
|
+
# when no language is given) as its first positional argument.
|
|
464
|
+
lang_or_template_id = namespace.template_id
|
|
465
|
+
if lang_or_template_id is None and not namespace.list:
|
|
466
|
+
lang_or_template_id = await self._active_prompts.prompt("Template ID")
|
|
414
467
|
|
|
415
468
|
self._invoke_command(
|
|
416
469
|
add_command.template,
|
|
417
|
-
|
|
470
|
+
lang_or_template_id=lang_or_template_id,
|
|
471
|
+
template_id=namespace.template_name,
|
|
418
472
|
list_templates=namespace.list,
|
|
419
473
|
force=namespace.force,
|
|
420
474
|
name=namespace.name,
|