⚡ Optimize marketplace list fetching with pagination#49
⚡ Optimize marketplace list fetching with pagination#49google-labs-jules[bot] wants to merge 862 commits intomainfrom
Conversation
Restructure the Add Source modal to support intelligent URL parsing and automatic field population. Changes: - Add `POST /api/v1/marketplace/sources/infer-url` endpoint (backend) - Add `InferUrlResponse` type to marketplace types - Create `lib/api/marketplace.ts` with `inferUrl` function - Add `useInferUrl` hook for URL inference mutation - Restructure modal with Quick Import and Manual Entry sections - Implement debounced URL inference (400ms) - Auto-populate manual fields when URL inference succeeds - Show loading and error states during inference - Add visual "Or" separator between sections - Move shared settings (frontmatter toggle, trust level) to bottom User flow: 1. User pastes GitHub URL (any format: repo, tree, blob) 2. System auto-detects repo_url, ref, and root_hint 3. Manual fields populate automatically 4. User can quick-import or adjust manually Frontend files: - skillmeat/web/types/marketplace.ts - skillmeat/web/lib/api/marketplace.ts (new) - skillmeat/web/hooks/useMarketplaceSources.ts - skillmeat/web/components/marketplace/add-source-modal.tsx Backend files: - skillmeat/api/routers/marketplace_sources.py - skillmeat/api/schemas/marketplace.py - tests/api/test_marketplace_sources.py 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused InferUrlResponse import from hooks - Fix test mocking for auto-scan in create_source tests - Fix SQLAlchemy model instantiation in update tests Refs: REQ-20260104-skillmeat-01 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refs: REQ-20260104-skillmeat-01 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Add Source modal's Quick Import field was causing constant flickering by hitting the infer-url API in an infinite loop. The issue was that `inferUrl` (a TanStack Query mutation object) was in the useEffect dependency array. When mutateAsync runs, the mutation state changes, creating a new object reference that triggered the effect to re-run. Fix: Use useRef to hold a stable reference to the mutation function, removing inferUrl from the dependency array so the effect only runs when quickImportUrl actually changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…sed tag extraction Feature: Extract organizational metadata from artifact source paths during marketplace scanning, allowing users to review and approve path segments before they become artifact tags on import. Includes: - PRD with requirements, acceptance criteria, and phased approach - Implementation plan with 3 phases (backend, frontend, import integration) - Phase-specific implementation files with task breakdowns - Progress tracking files with YAML frontmatter for orchestration - Context file with architectural decisions and file inventory 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds backend infrastructure for automatically extracting path segments
from artifact source paths during marketplace scanning. Users can review
and approve/reject extracted segments via API before importing.
## Database Layer
- Add path_tag_config column to marketplace_sources
- Add path_segments column to marketplace_catalog_entries
- Alembic migration with upgrade/downgrade support
## Core Business Logic
- PathTagConfig dataclass for extraction configuration
- ExtractedSegment dataclass for individual segments
- PathSegmentExtractor service with normalization and exclusion rules
- Pre-compiled regex patterns for performance (<50ms per extraction)
## API Layer
- Pydantic schemas: PathSegmentsResponse, UpdateSegmentStatusRequest
- GET /marketplace-sources/{id}/catalog/{entry_id}/path-tags
- PATCH /marketplace-sources/{id}/catalog/{entry_id}/path-tags
- Scanner integration for automatic extraction during scan
## Testing
- 63 unit tests for PathSegmentExtractor (100% coverage)
- 23 unit tests for API endpoints
- 12 integration tests for workflow validation
- 98 total tests passing
## Documentation
- Architecture doc: docs/dev/architecture/path-based-tags.md
- API reference: docs/dev/api/marketplace-sources.md
Phase 1 of 3 complete. Ready for Phase 2: Frontend Review UI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add getPathTags() and updatePathTagStatus() API functions - Create TypeScript types matching backend schemas - Export path-tags types from index Tasks: TASK-2.1, TASK-2.2 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add usePathTags hook for fetching path segments - Add useUpdatePathTagStatus mutation hook with cache invalidation - Add pathTagKeys factory for cache management Task: TASK-2.3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create PathTagReview component with approve/reject UX - Add StatusBadge, SegmentRow, and PathTagSummary sub-components - Implement loading, error, and empty states - Add accessibility: aria-labels, tooltips, keyboard navigation - Support dark mode and responsive design Task: TASK-2.4 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…atch 4) - Add "Suggested Tags" tab to CatalogEntryModal - Integrate PathTagReview component for path segment review - Add 21 unit tests for PathTagReview component (100% coverage) - Tests cover loading, error, empty states, approve/reject actions Tasks: TASK-2.5, TASK-2.8 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Accessibility (TASK-2.6): - Add aria-hidden to decorative icons - Convert segment list to semantic <ul>/<li> structure - Verified WCAG 2.1 AA compliance E2E Tests (TASK-2.7): - Add 16 Playwright tests for path tag workflow - Cover approve/reject, persistence, error handling - Add accessibility tests (ARIA, keyboard navigation) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All 8 tasks completed: - TASK-2.1: API client functions - TASK-2.2: TypeScript types - TASK-2.3: React Query hooks - TASK-2.4: PathTagReview component - TASK-2.5: CatalogEntryModal integration - TASK-2.6: Accessibility audit (WCAG 2.1 AA) - TASK-2.7: E2E tests (16 Playwright tests) - TASK-2.8: Component tests (21 tests, 100% coverage) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add path-based tag application during artifact import: Schema changes: - Add apply_path_tags field to BulkImportRequest (default: true) - Add tags_applied field to ImportResult - Add total_tags_applied field to BulkImportResult Backend implementation: - Add _apply_path_tags helper to ArtifactImporter - Extract path segments using PathSegmentExtractor - Apply approved/pending segments as tags to imported artifacts - Track tag counts in import results Frontend changes: - Add "Apply approved path tags" checkbox to BulkImportModal - Wire checkbox state to onImport callback - Update types to include apply_path_tags in request/response Refs: Phase 3, TASK-3.1, TASK-3.2, TASK-3.3, TASK-3.4 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive integration tests for apply_path_tags feature: - TestApplyPathTagsDefaultTrue: Verify tags applied when true (default) - TestApplyPathTagsFalse: Verify NO tags when false - TestPathSegmentExtraction: GitHub/local path extraction - TestExcludedSegments: Common directory filtering - TestNumericPrefixNormalization: 05-data-ai -> data-ai - TestEmptyPathHandling: Graceful empty path handling - TestMultipleArtifacts: total_tags_applied aggregation - TestTagDeduplication: No duplicate tags - TestImporterDirectIntegration: Direct _apply_path_tags tests - TestExtractedSegmentStatus: pending vs excluded segments - TestPathTagConfigVariations: Custom config tests 26 tests covering all path tag import scenarios. Refs: Phase 3, TASK-3.5 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…h 4) Add comprehensive E2E tests for "Apply approved path tags" checkbox: Core tests: - Checkbox visibility and default state (checked) - Toggle behavior (check/uncheck) - State persistence during artifact selection - Disabled state during import API integration tests: - Import sends apply_path_tags=true when checked - Import sends apply_path_tags=false when unchecked Edge case tests: - Multiple toggle cycles - Independent of artifact selection - Works with multiple artifacts - Label accessibility (clickable) 10 tests with browser variants (chromium, firefox, webkit). Refs: Phase 3, TASK-3.6 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ch 6) Update bulk import endpoint documentation with apply_path_tags feature: - Add apply_path_tags request parameter (boolean, default: true) - Add tags_applied field to ImportResult response - Add total_tags_applied field to BulkImportResult response - Update request/response examples with realistic tag counts - Update Python SDK example with apply_path_tags parameter - Update curl examples OpenAPI schema auto-generates from Pydantic models. Refs: Phase 3, TASK-3.8 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tection improvements REQ-20260104-skillmeat: Two enhancements for marketplace artifact detection: 1. Manual Source Mapping - UI to map directories to artifact types 2. Auto-detection Deduplication - SHA256-based duplicate removal Artifacts created: - PRD: docs/project_plans/PRDs/features/marketplace-source-detection-improvements-v1.md - Implementation Plan: docs/project_plans/implementation_plans/features/marketplace-source-detection-improvements-v1.md - Progress tracking: .claude/progress/marketplace-source-detection-improvements/ - Context notes: .claude/worknotes/marketplace-source-detection-improvements/ - Architecture reference: .claude/context/marketplace-source-detection.md 5 phases, 58 tasks, 65-96 story points, 4-5 weeks estimated 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Frontend API client used `/marketplace-sources/...` but backend router is registered at `/marketplace/sources/...` causing 404 errors on the Suggested Tags tab in Catalog Entry modal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Break all-phases-progress.md (948 lines) into 5 separate phase files: - phase-1-progress.md (121 lines) - Database & Schema - phase-2-progress.md (257 lines) - Backend Detection Engine - phase-3-progress.md (225 lines) - API Layer - phase-4-progress.md (286 lines) - Frontend UI - phase-5-progress.md (205 lines) - Testing & Documentation Per CLAUDE.md documentation policy: ONE progress file per phase. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split 1101-line plan into parent + extracted sections: - Parent plan: 488 lines (55% reduction) - Extracted to subdirectory: - quality-gates.md (92 lines) - metrics.md (47 lines) - deployment.md (79 lines) - data-structures.md (70 lines) Removed redundant sections: - Orchestration Quick Reference (covered by phase progress files) - Team & Responsibilities (covered by assigned_to in progress files) Progressive disclosure: agents load parent overview, then specific sections only when needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…dels Phase 1 of marketplace source detection improvements: - Validated existing manual_map column (MarketplaceSource.manual_map) - Validated metadata_json column (MarketplaceCatalogEntry.metadata_json) - Created comprehensive schema documentation (.claude/context/marketplace-schema.md) - Added Pydantic schemas: ManualMapEntry, ManualMapRequest, DeduplicationStats No database migrations needed - reusing existing columns with JSON storage. Foundation complete for Phase 2 backend detection engine. Refs: Phase 1 complete (P1.1, P1.2, P1.3, P1.4) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2 Batch 2.1: - P2.1a: Updated detect_artifacts() signature with optional manual_mappings parameter - P2.2a: Created content_hash.py with SHA256 hashing for files and artifacts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…e limits Phase 2 Batch 2.2: - P2.1b: Implemented exact/prefix directory matching for manual mappings - P2.2b: Added ContentHashCache class for caching computed hashes - P2.2c: Added 10MB file size limit to prevent timeout on large files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… and hash tests Phase 2 Batch 2.3: - P2.1c: Implemented hierarchical inheritance with depth tracking - P2.2d: Added comprehensive unit tests for content hashing (52 tests) - P2.3a: Created DeduplicationEngine class with best-artifact selection 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tion Phase 2 Batch 2.4: - P2.1d: Confidence scoring based on inheritance depth (95→86 scale) - P2.3b: deduplicate_within_source() method with exclusion metadata 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ests Phase 2 Batch 2.5: - P2.1e: Comprehensive unit tests for manual mapping (86 tests, 90% coverage) - P2.3c: deduplicate_cross_source() method for existing collection matching 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2 Batches 2.6-2.7: - P2.3d: Exclusion marking helpers with standardized constants - P2.3e: Comprehensive deduplication unit tests (75 tests, 100% coverage) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2 Batch 2.8: - P2.4a: Integrated DeduplicationEngine into github_scanner.py - Added get_existing_collection_hashes() for cross-source dedup - Updated ScanResultDTO with dedup statistics - Added comprehensive integration test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
E2E tests (TEST-005, TEST-006, TEST-007): - Source import with repo details and tags - Filtering by artifact type, tags, trust level - Combined filters with AND logic - Repo details modal display and keyboard nav Accessibility tests (TEST-008): - jest-axe automated checks for all components - WCAG 2.1 AA compliance verification - Keyboard navigation tests - Screen reader compatibility - Focus management and ARIA labels 70 accessibility tests, 3 E2E test files created Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…rces Performance tests (TEST-009): - Source list <200ms with 500+ sources - Detail fetch <5s - Filter query scaling - Concurrent request performance Security tests (TEST-010): - Tag validation whitelist (70+ injection payloads) - XSS, SQL injection, template injection prevention - Path traversal blocking - Input sanitization - Rate limiting verification Coverage (TEST-011): 86% schema coverage, 48% router coverage (router includes many unrelated features) 183 new backend tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add two comprehensive user guides for the marketplace sources enhancement: - source-import.md: Step-by-step guide to importing sources with repository details, tags, and trust levels - source-filtering.md: Complete guide to filtering and discovering sources by type, tags, and trust level Both guides include screenshots placeholders, use cases, best practices, and troubleshooting tips aligned with the feature specification. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
API Documentation (DOC-001): - Endpoint reference for marketplace sources filtering - Request/response schemas with examples Component Documentation (DOC-002): - SourceFilterBar, TagBadge, CountBadge, RepoDetailsModal - Props tables, usage examples, accessibility notes User Guides (DOC-003, DOC-004): - Source import with repo details and tags - Source filtering with AND logic ADRs (DOC-005, DOC-006): - Repository metadata storage strategy - Filter implementation with AND semantics Release Notes (DOC-007): - CHANGELOG entry for marketplace sources enhancement v1 Developer Guide (DOC-008): - Extending source filters and metadata Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
I investigated and fixed three bugs in the marketplace sources feature: Bug 1: update_source endpoint not handling import_repo_description, import_repo_readme, and tags File: skillmeat/api/routers/marketplace_sources.py The update_source endpoint had the fields defined in the schema but: - They weren't included in the validation check - They weren't applied when updating the source Fixed by: - Adding these fields to the validation check (lines 1247-1249) - Adding logic to store tags using source.set_tags_list() (lines 1298-1299) - Adding logic to fetch repo_description from GitHub API when import_repo_description=True (lines 1302-1316) - Adding logic to fetch README from GitHub when import_repo_readme=True (lines 1319-1358) - Same changes for create_source endpoint (lines 803-857) Bug 2: counts_by_type not being computed during scans File: skillmeat/api/routers/marketplace_sources.py The scan was updating artifact_count but not computing counts_by_type, causing all source cards to show "0". Fixed by: - Computing counts_by_type from scan results (lines 509-513) - Storing counts_by_type on the source within the transaction (lines 524-529) - Adding Dict to typing imports (line 31) Bug 3: source_to_response missing fields File: skillmeat/api/routers/marketplace_sources.py The source_to_response function wasn't returning the new fields. Fixed by: - Adding repo_description, repo_readme, tags, and counts_by_type to the response (lines 326-329) Validation Results All fixes were validated in the browser: - ✅ Tags now display on source cards (tested with "test-agents" tag) - ✅ Artifact counts now show correct values (128 instead of 0) - ✅ Descriptions display correctly (user-provided with repo_description as fallback) - ✅ Import toggles work - enabling "Re-fetch repository description" and "Re-fetch README content" successfully triggers fetching from GitHub
- Replace inline badge-based tag filter with searchable dropdown popover on sources page, matching collection page pattern with multi-select, source counts, and deterministic hash-based colors - Add TagBadge display to source detail page header showing source tags with clickable navigation to filtered sources list - Fix README field name mismatch: frontend now uses `repo_readme` to match backend response instead of `readme_content` Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add overflow-hidden and min-w-0 constraints to enable proper scroll behavior within the modal. The README content now stays within the visible modal viewport with its own scrollbar, keeping the repo title and description fixed at top. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…scroll The previous fix using ScrollArea wasn't working because the modal lacked an explicit height constraint. This fix: - Adds explicit h-[85vh] alongside max-h-[85vh] so flex children have defined height bounds to calculate against - Replaces ScrollArea with native overflow-y-auto which is simpler and more reliable for this use case - Removes unused ScrollArea import The README content now properly scrolls within the modal while the repo title and description remain fixed at top. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend changes for Collections & Groups UX Enhancement: - Add query filters to groups router (artifact_id, group_id, include_groups) - Update user_collections schema with group membership info - Regenerate TypeScript SDK with new models and services New SDK models: - ArtifactCollectionInfo, ArtifactGroupMembership - CopyGroupRequest, CollectionMatch - Various discovery/marketplace enhancements Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement TanStack Query hooks for group management: - useGroups: Fetch groups for a collection with 5min stale time - useArtifactGroups: Query which groups contain a specific artifact - useGroupArtifacts: Fetch artifacts within a group - Cache invalidation with hierarchical query keys New files: - hooks/use-artifact-groups.ts - __tests__/hooks/use-groups.test.tsx - __tests__/hooks/use-artifact-groups.test.tsx Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add collection membership indicators to UnifiedCard: - CollectionBadgeStack: Shows up to 2 collection badges + overflow - Conditional rendering for "All Collections" view - Radix Tooltip for overflow badge showing full list - Uses shadcn Badge (secondary variant) New files: - components/shared/collection-badge-stack.tsx - __tests__/components/collection-badge-stack.test.tsx Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add group membership indicators to cards and detail modal: - GroupBadgeRow: Shows groups artifact belongs to (outline badges) - GroupsDisplay: Full groups section for artifact detail modal - Enhanced ModalCollectionsTab with groups section - Uses useArtifactGroups hook for data fetching New files: - components/shared/group-badge-row.tsx - components/entity/groups-display.tsx - __tests__/components/group-badge-row.test.tsx - __tests__/components/groups-display.test.tsx Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add dedicated /groups page for browsing artifacts by group: - Groups nav item in sidebar under Collections section - GroupSelector dropdown for choosing groups - GroupArtifactGrid with infinite scroll pagination - Grid/List view toggle with localStorage persistence - Comprehensive empty states and loading skeletons New files: - app/groups/page.tsx (server component) - app/groups/components/groups-page-client.tsx - app/groups/components/group-selector.tsx - app/groups/components/group-artifact-grid.tsx - __tests__/pages/groups-page.test.tsx - __tests__/components/group-selector.test.tsx - __tests__/components/group-artifact-grid.test.tsx Test coverage: 60 tests, all passing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Planning and progress tracking: - PRD and implementation plans for collections-groups-ux-enhancement - Phase progress files (phases 0-5) - Worknotes and context documentation Component updates and test fixes: - Updated collection, discovery, marketplace components - Updated deployment, notification, sync components - Test file updates for new hook signatures - E2E test updates for groups functionality Documentation: - CLAUDE.md updates for web frontend - Accessibility audit summaries - README performance report Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add GroupFilterSelect component for filtering artifacts by group on /collection and /manage pages. The filter is conditionally visible only when viewing a specific collection (hidden in "All Collections"). Changes: - Create GroupFilterSelect component with shadcn Select - Integrate into Filters component (collection page) - Integrate into EntityFilters component (manage page) - Add groupId to ArtifactFilters type - Add comprehensive unit tests (30 tests, 100% coverage) Completes Phase 5 of Collections & Groups UX Enhancement. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- CHANGELOG.md: Add feature entry for Phases 0-5 - skillmeat/api/CLAUDE.md: Document enhanced endpoints (artifact_id, group_id, include_groups) - skillmeat/web/CLAUDE.md: Add Collections & Groups components section Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show "Already in Group" state for groups artifact belongs to with greyed-out row, disabled checkbox, and amber text indicator - Add "Remove from Group" icon button with tooltip for quick removal without closing dialog - Add "Add to Group" button to UnifiedEntityModal Collections tab - Update tests with mocks for new hooks (useArtifactGroups, useRemoveArtifactFromGroup) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The DELETE endpoint for removing artifacts from groups returns HTTP 204 (No Content), but apiRequest was attempting to parse JSON from the empty response body, causing a SyntaxError. Root cause: response.json() throws when called on empty body, even when content-type header indicates JSON. This fix adds an early return for 204 status codes, properly handling void-returning endpoints and ensuring onSuccess callbacks fire correctly for cache invalidation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…or "Failed to execute 'json' on 'Response': Unexpected end of JSON input" and didn't update the UI.
Root Cause: The apiRequest function in lib/api.ts was attempting to parse JSON from HTTP 204 No Content responses. The DELETE endpoint correctly returns 204 with an empty body, but calling response.json() on an empty body throws a SyntaxError. This caused the mutation to appear to fail (throwing an error), which prevented the onSuccess callback from firing and the cache from being invalidated.
Fix: Added early return handling for HTTP 204 status codes in apiRequest():
if (response.status === 204) {
trace('request:success', { url, status: response.status });
return undefined as T;
}
This ensures void-returning endpoints work correctly and cache invalidation fires properly.
When a user adds a Marketplace Source for a GitHub repo that IS itself an artifact (e.g., a skill with SKILL.md at root), the detection algorithm wouldn't find it. This adds an optional toggle to treat the entire repo as one artifact of a manually specified type. Backend: - Add single_artifact_mode and single_artifact_type to CreateSourceRequest - Add Pydantic validator requiring type when mode is enabled - Add columns to MarketplaceSource model with Alembic migration - Update _perform_scan to bypass scanner and create synthetic artifact with 100% confidence when mode is enabled - Update SourceResponse schema to include new fields Frontend: - Add "Treat as single artifact" toggle in AddSourceModal settings - Add conditional artifact type selector (skill/command/agent/mcp/hook) - Update types in marketplace.ts Also: - Regenerate OpenAPI SDK (includes unrelated formatting changes) - Update CHANGELOG with feature documentation - Add Single Artifact Mode section to marketplace-github-sources.md guide Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SPIKE researching enhancement of /marketplace/sources search to support searching detected artifacts across all sources from a single location. Key findings: - Feasibility: HIGH - moderate complexity, phased implementation - Phase 1: Extend SQLite schema with denormalized search columns (~3 days) - Phase 2: Add FTS5 full-text search if basic search insufficient (~2 days) - Phase 3: Frontend dual-mode toggle UI (~2 days) Technical highlights: - Zero additional GitHub API calls (frontmatter extracted during scan) - Storage: ~850 bytes/artifact, ~42MB for 50K entries - Query performance: <50ms at 50K scale with LIKE; <10ms with FTS5 - Uses existing SQLite/SQLAlchemy infrastructure Includes architecture analysis, UI design recommendations, and ADR guidance. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ter caching Feature: Configurable Frontmatter Caching for Cross-Source Artifact Search Phase 0 of the cross-source artifact search SPIKE New documents: - PRD: docs/project_plans/PRDs/enhancements/configurable-frontmatter-caching-v1.md - Implementation Plan: docs/project_plans/implementation_plans/enhancements/configurable-frontmatter-caching-v1.md - Progress Tracking: .claude/progress/configurable-frontmatter-caching-v1/ - Context Worknotes: .claude/worknotes/configurable-frontmatter-caching-v1/ Feature adds: - Global config: artifact_search.indexing_mode (off|on|opt_in) - Per-source override: indexing_enabled boolean on MarketplaceSource - UI toggle in add/edit source dialogs with mode-aware visibility Implementation: 22 tasks across 6 phases (~26 story points) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Addresses critical issues in the in-memory caching implementation: - Add threading.RLock() to protect cache operations in concurrent async environment - Return deepcopy of cached Collection objects to prevent callers from mutating cache - Add invalidate_collection_cache() public method for external cache invalidation - Fix import_coordinator.py to invalidate cache after direct manifest writes - Add debug logging when cache fallback occurs These changes ensure the cache is safe for production use with FastAPI's concurrent request handling. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds skip and limit parameters to list_marketplace_entries in CacheRepository to avoid fetching all entries when only a subset is needed. This provides a significant performance improvement for large datasets. Benchmark results showed a ~60x speedup when fetching 100 items from a dataset of 10,000 items (0.1675s -> 0.0028s). Fixes #issue-id (if applicable)
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
💡 What:
list_marketplace_entriesinskillmeat/cache/repository.pyto acceptskip(default 0) andlimit(default 100) parameters..offset(skip)and.limit(limit).🎯 Why:
list_marketplace_entriesfetched all matching rows from the database.list_projectswhich already support pagination.📊 Measured Improvement:
limit=100) took 0.0028 seconds.skillmeat/cache/tests/test_marketplace_performance.pyandtests/test_cache_repository.pyto ensure no regressions. All tests passed.PR created automatically by Jules for task 3286370322012691165 started by @miethe