Feature/user style management#120
Draft
ShotaroKataoka wants to merge 34 commits intomainfrom
Draft
Conversation
SPEC: 20260503-0854_user-style-management Progress: Phase 1a complete - StyleCard: ★ pin button (hover fade-in, bounce animation, stopPropagation) - Pinned section + All Styles collapsible when pins exist - Flat grid when no pins (backward compatible) - Preview header: ★ pin toggle next to style name - Custom badge for user styles - Scroll position preserved on pin toggle - StyleEntry type: added pinned/source fields with backfill defaults Next: Phase 1b — Engine + API layer
…ucture SPEC: 20260503-0854_user-style-management Progress: Phase 1b complete - config.py: get_state() / update_state() for state.json - reference/__init__.py: filter_styles() pure function (I/O-free) - api.py: list_styles_filtered() filesystem entry point - tools.py: list_styles with include_all, browser open removed - server.py: include_all parameter on MCP tool - server_acp.py: fixed to use tools.py (user-local styles now visible) - 21 tests passing (9 new) Next: Phase 1c — Local API Routes + frontend API connection
…tion SPEC: 20260503-0854_user-style-management Progress: Phase 1c (Local portion) complete - sdpmPaths.ts: shared helpers for config dir, state.json, style listing - GET /api/styles: user-local + bundled with pinned/source metadata - GET /api/styles/[name]: search user-local first, then bundled - POST /api/styles/pin: pin toggle persisted to state.json - deckService.ts: pinStyle() API function - SpecStepNav: optimistic pin toggle connected to API Next: Phase 1c — Cloud layer (DynamoDB pins, MCP Server)
SPEC: 20260503-0854_user-style-management Progress: Phase 2 — /styles page + AppShell tabs - AppShell: Decks | Styles tab navigation (active state, hidden in workspace) - /styles page: user styles (top, with delete) + built-in styles grid - Style preview with iframe scaling (1920×1080) - Pin toggle on cards and preview - Custom badge for user styles Next: Phase 2 — Engine save/delete + API routes
…s page polish SPEC: 20260503-0854_user-style-management - StyleSlidePreview: shared component for style/art-direction rendering - Resets body zoom/padding/margin, preserves slide border/outline - 2200px iframe width to accommodate decorative borders - 8px gap between slides - /styles page: full-width preview, dynamic card scaling - SpecStepNav: art-direction result now uses StyleSlidePreview - sdpmPaths: cover extraction uses div.slide, resets body zoom - Removed duplicate StylePreviewInline and inline iframe code
Change StyleCard from <button> to <div role=button> to allow nested pin <button> without violating HTML spec.
…UX polish SPEC: 20260503-0854_user-style-management Phase 2 + Phase 4 (pulled forward): API Routes: - POST /api/styles/user — save user style (title tag validation) - DELETE /api/styles/user/[name] — delete user style Service layer: - saveUserStyle(), deleteUserStyle() in deckService.ts /styles page: - Create with AI card (primary) + Import Style link (secondary) - Delete with confirmation dialog (Esc, aria-modal, autoFocus) - Export (HTML download) on hover + preview header - Toast notifications replacing alert() for import/delete feedback - Touch target fix on Import Style link Bug fix: - Slide class regex: class="slide" missed variants like slide--dark, slide-alt. Changed to class="slide[\s"] Fixes corporate-executive (4→6) and cute-playful (2→4)
…tyles default open SPEC: 20260503-0854_user-style-management Progress: Phase 2.5 + Phase 2.7 complete - apply_style: use _find_style_in_dirs for user style support - /styles page: migrate to useStyleWorkspace hash routing - Add Copy to My Styles for builtin styles - All Styles collapsible default open (UX: Anticipatory Design)
…onents SPEC: 20260503-0854_user-style-management Progress: Phase 3a (partial) + Phase 3b complete New shared components: - useChatStream hook: streaming state management core - ChatInput: reusable input with PlusMenu, attachments, IME - useStyleWorkspace: hash routing for /styles page Style chat UI: - StyleChatPanel: lightweight orchestrator using shared components - StyleChatShell: resizable side panel (mirrors ChatPanelShell UX) - /styles page: #create → Untitled Style + chat open (Notion pattern) - User style preview: 'Edit with AI' button opens chat panel - Live preview via onStyleHtmlUpdate (tool result → iframe) - MODE_TO_AGENT: style → sdpm-style
… + agent definition SPEC: 20260503-0854_user-style-management Progress: Phase 3c (sandbox + tool) and Phase 3d (agent def + prompt + save callback) complete - sandbox.py: make_style_runner() with read_style helper - server_acp.py: run_style_python tool (workspace, save, live preview) - sdpm-style.json: ACP agent definition - style-creator.md: agent prompt - StyleChatPanel: onStyleSaved callback for toast + refresh Next: Manual integration test with WebUI
Root cause: ChatInput's FileDropZone wrapper had h-full, expanding to fill parent flex container and pushing messages area to zero height. Fix: Add className prop to FileDropZone, pass 'relative' (no h-full) from ChatInput. Existing callers use default 'relative h-full'.
SPEC: 20260505-1330_style-chat-ux-polish - R1: Elevate Edit with AI to primary CTA (brand-teal, Sparkles icon) - R2: Add prompt chips to welcome screen for cognitive load reduction - R3: Header already shows styleName (no change needed)
…aming/rename UI - sandbox: remove workspace (tempdir), expose read_style/write_style only - server_acp: remove style_id/save params, direct write to user styles dir - StyleChatPanel: inject [Style: name] on first message for agent context - /styles page: name input dialog for create, ⋯ menu with rename/export/delete - API: PATCH /styles/user/[name] for rename (with pin reference update) - Preview header: ★ + Edit with AI + ⋯ menu (clean layout) - Card: ★ only on hover, ⋯ menu fixed-position (no overflow clip) - useStyleWorkspace: refreshPreview() for post-write refetch - style-creator.md: updated prompt for new write_style(name, html) API SPEC: 20260503-0854_user-style-management Progress: Phase 3c refactored, naming/rename UI added
…lity hints Replace prompt hint buttons and plain text with icon + short phrase layout showing agent capabilities (describe, drop image, customize). Follows UX Excellence Instant Clarity principle.
…is to agent directly - upload_file() now returns filePath (absolute) and colorAnalysis for images - [Attached:] marker uses path format in Local mode (quoted for spaces) - Remove read_uploaded_file MCP tool from ACP (agent uses read tool directly) - Color analysis: PIL quantize (5 colors), brightness, saturation (~8ms) - Fix uploadService.ts to propagate filePath/colorAnalysis from API response SPEC: 20260506-1033_acp-upload-path-direct-access
…n env unset
Path('') evaluates to PosixPath('.') which is truthy, so the 'or'
fallback to ~/Documents/SDPM-Presentations never triggered.
This caused .sessions/ to be created in cwd (mcp-local/) instead.
Fix: check the string value before constructing Path.
- Create with AI: auto-generate style-{YYYYMMDD-HHMM} name (no dialog)
- Inline rename: click name in card list to edit in-place
- Inline validation errors (edit mode stays open on error)
- Pencil icon affordance on name hover
- Replace ⋯ dropdown with direct icon buttons (★ Export Delete)
- Remove <title> tag validation (sandbox, API, import)
SPEC: 20260503-0854_user-style-management
- Extract shared logic into useChatStream hook and ChatInput component - Remove slidePreviewUrls prop (unused after refactor) - Remove onSlideClick handler (moved to different interaction) - Add ModelSelector component - Add attachmentMarker utility - StyleChatPanel/Shell minor adjustments SPEC: 20260503-0854_user-style-management
ChatInput extraction moved FileDropZone to input-only scope. Restore panel-wide drop target by wrapping ChatPanel and StyleChatPanel roots with FileDropZone, delegating to ChatInput.addFiles() via imperative handle. SPEC: 20260503-0854_user-style-management
SPEC: 20260503-0854_user-style-management
Phase: 1d, 2 Cloud, 2.5 Cloud, 3e
- Storage: get_style_pins/put_style_pins (DynamoDB PK=USER#, SK=STYLE_PINS)
- list_styles: user styles (S3 user-styles/{user_id}/) + pins + filter_styles
- apply_style: search user styles before builtin
- run_style_python: Code Interpreter sandbox with style.html + ref/ workspace
- API Gateway: POST /styles/pin, POST /styles/user, DELETE/PATCH /styles/user/{name}
- api/index.py: 6 endpoints (GET×2 revised, 4 new)
- Agent: MODES["style_creator"] with allowed_tools filtering via MCPClient tool_filters
- Tool isolation: _DECK_TOOLS (19) / _STYLE_TOOLS (4) allowlists
- Local agents: explicit allowlist replacing @sdpm/* wildcard
- Add setAgentConfig call (was missing, causing 'ARN not configured') - Fix mode: 'style' → 'style_creator' to match MODES key
- _DECK_TOOLS: add list_asset_sources, list_templates, search_assets; remove non-MCP hearing - _STYLE_TOOLS: add read_uploaded_file, remove hearing - upload.py: add _analyze_colors() for image color palette extraction
StyleChatPanel sends mode='style_creator' but MODE_TO_AGENT had 'style', causing Local mode to fall back to sdpm-spec agent instead of sdpm-style.
…h extra classes _extract_cover_html used exact match '<div class="slide">' which missed slides with additional classes like 'slide slide--dark'. Now uses regex pattern matching '<div class="slide[\s"]' consistent with Local version.
…nagement # Conflicts: # web-ui/src/components/chat/ChatPanel.tsx
…atch block Port PR#118 error classification to useChatStream.ts where streaming logic now lives in this branch.
Defense-in-depth: validate resolved path stays within styles dir. The regex check already prevents traversal, but realpath check satisfies CodeQL's taint tracking.
- ChatInput: move handleFilesRef assignment into useEffect - useStyleWorkspace: replace useRef with useState lazy initializer
…CP Local, WebUI SPEC: 20260506-2312_user-template-management Phase 1: Engine API (list_templates_with_metadata, analyze_and_store_template) - Extract _extract_theme_colors_raw to analyzer (decouple from builder) - MCP Local list_templates returns metadata from state.json Phase 2: WebUI /templates page (Local version) - API Routes: GET list, GET download, POST upload, PATCH rename/description, DELETE - Template cards with theme preview strip, color palette, fonts, layout count - Upload dialog with drag-and-drop, description input, analysis spinner - Inline editable name (with lint) and description for user templates - AppShell: Decks | Styles | Templates navigation Next: Phase 3 (Cloud layer — S3 + DDB + MCP Server)
- Persist analyzed metadata for builtin and user templates
- Skip Python analysis on subsequent requests (read from cache)
- Builtin cached as 'builtin:{name}', user as '{name}'
SPEC: 20260506-2312_user-template-management
- Delete dialog: opaque bg, backdrop-blur, entry animation, deeper shadow - Preview more-menu: opaque bg, backdrop-blur, larger touch targets SPEC: 20260506-2312_user-template-management
- Storage ABC: 7 user template CRUD methods (list/get/put/delete/download/rename/update)
- AwsStorage: DDB (USER#{user_id}/TEMPLATE#{name}) + S3 (user-templates/{user_id}/) impl
- MCP Server: list_templates + analyze_template now accept user_id, search user templates
- API Lambda: GET/POST/DELETE/PATCH /templates endpoints with multipart upload + analysis
- api/requirements.txt: add python-pptx + lxml for in-Lambda template analysis
- CDK: API Gateway routes + Lambda bundling includes sdpm/analyzer module
SPEC: 20260506-2312_user-template-management
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User Style Management
Add user-created style support with pin (favorites), gallery UI,
/stylespage, and AI-powered style creation.What changed
Pin & Gallery (Phase 1)
list_stylesAPI extended withinclude_allparam, returnspinned/sourcemetadatafilter_styles()pure function shared across MCP Local and MCP ServerUser Styles &
/stylesPage (Phase 2)/stylespage (Decks | Styles nav tabs)#create,#{name}for preview/edituser-styles/{user_id}/+ DynamoDBSTYLE_PINS~/.config/sdpm/styles/+state.jsonStyle Creator Agent (Phase 3)
run_style_pythontool — sandboxed Python execution for style HTML generationread_style(name)/write_style(name, html)sandbox helpersstyle.html+ref/{name}.htmlworkspaceuseChatStreamhook +ChatInputcomponent extracted from ChatPanel (shared)StyleChatPanel+StyleChatShell— dedicated chat UI for style creationsdpm-style.json) + role promptstyle_creatorwith_STYLE_TOOLSallowlistallowed_toolsin ModeConfig → MCPClienttool_filtersBug fixes in this PR
apply_stylenow searches user styles (Local + Cloud)_extract_cover_htmlhandles slides with extra CSS classes (slide slide--dark)MODE_TO_AGENTkey fixed (style_creatornotstyle)Testing
test_styles_resolution.py(141 tests pass)Out of scope