diff --git a/.planning/phases/27-node-defaults-infrastructure/27-01-PLAN.md b/.planning/phases/27-node-defaults-infrastructure/27-01-PLAN.md new file mode 100644 index 00000000..95fee506 --- /dev/null +++ b/.planning/phases/27-node-defaults-infrastructure/27-01-PLAN.md @@ -0,0 +1,191 @@ +--- +phase: 27-node-defaults-infrastructure +plan: 01 +type: execute +--- + + +Create infrastructure for storing default model and settings preferences per node type. + +Purpose: Enable users to configure default models for GenerateImage, GenerateVideo, and LLM nodes so keyboard shortcuts and quick-add buttons create nodes with their preferred settings. +Output: NodeDefaults types, localStorage persistence, and integration with createDefaultNodeData. + + + +~/.claude/get-shit-done/workflows/execute-phase.md +~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md + +**Key files:** +@src/store/utils/localStorage.ts +@src/store/utils/nodeDefaults.ts +@src/types/nodes.ts +@src/types/providers.ts + +**Current state:** +- GenerateImageDefaults already exists in localStorage.ts for nanoBanana node +- createDefaultNodeData() uses loadGenerateImageDefaults() for nanoBanana type +- generateVideo and llmGenerate use hardcoded defaults +- Node creation via Shift+G, Shift+L shortcuts calls addNode() → createDefaultNodeData() + +**Established patterns:** +- localStorage helpers: load{X}(), save{X}() with SSR-safe typeof window checks +- Defaults merged with existing settings to handle schema evolution +- Types defined in src/types/*.ts, re-exported from index.ts + +**Constraining decisions:** +- Phase 23: Recently used models stored per-model, not per-node-type +- Existing GenerateImageDefaults: {aspectRatio, resolution, model, useGoogleSearch} + + + + + + Task 1: Define node defaults types and localStorage helpers + src/types/nodes.ts, src/types/index.ts, src/store/utils/localStorage.ts + +1. Add NodeDefaultsConfig interface to src/types/nodes.ts (at end of file): + +```typescript +/** + * Default settings for node types - stored in localStorage + */ +export interface GenerateImageNodeDefaults { + selectedModel?: { + provider: ProviderType; + modelId: string; + displayName: string; + }; + aspectRatio?: string; + resolution?: string; + useGoogleSearch?: boolean; +} + +export interface GenerateVideoNodeDefaults { + selectedModel?: { + provider: ProviderType; + modelId: string; + displayName: string; + }; +} + +export interface LLMNodeDefaults { + provider?: LLMProvider; + model?: LLMModelType; + temperature?: number; + maxTokens?: number; +} + +export interface NodeDefaultsConfig { + generateImage?: GenerateImageNodeDefaults; + generateVideo?: GenerateVideoNodeDefaults; + llm?: LLMNodeDefaults; +} +``` + +Import ProviderType from ./providers.ts and LLMProvider, LLMModelType from existing imports. + +2. Re-export from src/types/index.ts: + - Add: GenerateImageNodeDefaults, GenerateVideoNodeDefaults, LLMNodeDefaults, NodeDefaultsConfig + +3. Add localStorage helpers to src/store/utils/localStorage.ts: + - STORAGE_KEY: "node-banana-node-defaults" + - loadNodeDefaults(): NodeDefaultsConfig + - saveNodeDefaults(config: NodeDefaultsConfig): void + - Helpers: getGenerateImageDefaults(), getGenerateVideoDefaults(), getLLMDefaults() + - Each getter returns undefined if not set, allowing fallback to hardcoded defaults + +Pattern: Follow existing getProviderSettings() pattern with SSR guard and JSON parse/stringify. + +Do NOT remove existing GenerateImageDefaults - it stays for backward compatibility. + + npm run build passes without TypeScript errors + NodeDefaultsConfig types exist, localStorage helpers compile, exports are in place + + + + Task 2: Integrate node defaults into createDefaultNodeData + src/store/utils/nodeDefaults.ts + +1. Import new types and helpers: + - Import loadNodeDefaults from ./localStorage + - Import GenerateImageNodeDefaults, GenerateVideoNodeDefaults, LLMNodeDefaults from @/types + +2. Update createDefaultNodeData for nanoBanana case: + - Load node defaults: const nodeDefaults = loadNodeDefaults(); + - Get generateImage defaults: nodeDefaults.generateImage + - If selectedModel is set in nodeDefaults.generateImage, use it + - Fall back to existing loadGenerateImageDefaults() for aspectRatio/resolution/model/useGoogleSearch + - Merge: nodeDefaults.generateImage overrides legacy GenerateImageDefaults + +Priority for nanoBanana: +1. nodeDefaults.generateImage.selectedModel (if set) +2. Else: construct from loadGenerateImageDefaults().model as Gemini model + +3. Update createDefaultNodeData for generateVideo case: + - If nodeDefaults.generateVideo?.selectedModel is set, use it + - Otherwise keep undefined (user must select model) + +4. Update createDefaultNodeData for llmGenerate case: + - If nodeDefaults.llm exists, merge with hardcoded defaults + - Hardcoded: provider="google", model="gemini-3-flash-preview", temperature=0.7, maxTokens=8192 + - Override with any fields set in nodeDefaults.llm + +Keep the function efficient - only call loadNodeDefaults() once per node creation (cache at top of switch). + + npm run build passes, npm test passes (existing tests should not break) + createDefaultNodeData uses stored defaults when available, falls back to hardcoded defaults when not set + + + + Task 3: Add tests for node defaults persistence + src/store/utils/__tests__/localStorage.test.ts, src/store/utils/__tests__/nodeDefaults.test.ts + +1. Add tests to localStorage.test.ts for new helpers: + - loadNodeDefaults returns empty object when not set + - saveNodeDefaults persists to localStorage + - getGenerateImageDefaults returns undefined when not configured + - getGenerateImageDefaults returns stored value when configured + - Same pattern for getGenerateVideoDefaults and getLLMDefaults + +2. Add tests to nodeDefaults.test.ts for createDefaultNodeData integration: + - nanoBanana uses default Gemini model when no node defaults set (existing behavior) + - nanoBanana uses stored selectedModel when generateImage defaults set + - generateVideo uses stored selectedModel when generateVideo defaults set + - llmGenerate uses stored provider/model when llm defaults set + - llmGenerate falls back to hardcoded when llm defaults not set + +Mock localStorage using existing pattern from localStorage.test.ts. + + npm test -- --run passes all new and existing tests + Tests verify defaults loading/saving and createDefaultNodeData integration + + + + + +Before declaring plan complete: +- [ ] `npm run build` succeeds without TypeScript errors +- [ ] `npm test` passes all tests +- [ ] NodeDefaultsConfig types properly exported +- [ ] localStorage helpers work with SSR (typeof window check) +- [ ] createDefaultNodeData respects stored defaults + + + + +- All tasks completed +- TypeScript builds without errors +- Tests pass for new functionality +- Node defaults infrastructure ready for Phase 28 UI +- Backward compatible with existing GenerateImageDefaults + + + +After completion, create `.planning/phases/27-node-defaults-infrastructure/27-01-SUMMARY.md` +