Skip to content

refactor: extract shared AI chat components and hooks from views#59

Merged
2witstudios merged 4 commits intomasterfrom
claude/refactor-assistant-view-01CppokxNUDJ5A986XKHMMNc
Nov 27, 2025
Merged

refactor: extract shared AI chat components and hooks from views#59
2witstudios merged 4 commits intomasterfrom
claude/refactor-assistant-view-01CppokxNUDJ5A986XKHMMNc

Conversation

@2witstudios
Copy link
Owner

Major refactoring to consolidate duplicated code between GlobalAssistantView
and AiChatView into shared infrastructure:

Shared Hooks (lib/ai/shared/hooks/):

  • useMCPTools: MCP tool fetching and state management
  • useConversations: Conversation CRUD operations
  • useMessageActions: Edit, delete, retry message handlers
  • useProviderSettings: AI provider configuration loading

Shared Components (components/ai/chat/):

  • MCPToggle: MCP enable/disable toggle
  • ChatMessagesArea: Scrollable message display with loading skeleton
  • ChatInputArea: Input area with error display and send/stop buttons
  • StreamingIndicator: "Thinking..." indicator during AI response
  • ProviderSetupCard: API key setup prompt

Shared Types (lib/ai/shared/):

  • ProviderSettings, MCPToolSchema, ConversationData types
  • getAIErrorMessage utility for user-friendly error messages

Results:

  • GlobalAssistantView: 1377 → 746 lines (46% reduction)
  • AiChatView: 985 → 451 lines (54% reduction)
  • Total saved: ~1165 lines of duplicated code

This establishes an engine-centric architecture where Agent (AI_CHAT pages)
and Global Assistant engines share common chat infrastructure while
maintaining their distinct behaviors.

Major refactoring to consolidate duplicated code between GlobalAssistantView
and AiChatView into shared infrastructure:

Shared Hooks (lib/ai/shared/hooks/):
- useMCPTools: MCP tool fetching and state management
- useConversations: Conversation CRUD operations
- useMessageActions: Edit, delete, retry message handlers
- useProviderSettings: AI provider configuration loading

Shared Components (components/ai/chat/):
- MCPToggle: MCP enable/disable toggle
- ChatMessagesArea: Scrollable message display with loading skeleton
- ChatInputArea: Input area with error display and send/stop buttons
- StreamingIndicator: "Thinking..." indicator during AI response
- ProviderSetupCard: API key setup prompt

Shared Types (lib/ai/shared/):
- ProviderSettings, MCPToolSchema, ConversationData types
- getAIErrorMessage utility for user-friendly error messages

Results:
- GlobalAssistantView: 1377 → 746 lines (46% reduction)
- AiChatView: 985 → 451 lines (54% reduction)
- Total saved: ~1165 lines of duplicated code

This establishes an engine-centric architecture where Agent (AI_CHAT pages)
and Global Assistant engines share common chat infrastructure while
maintaining their distinct behaviors.
Enable rich message rendering (todo lists, socket updates) in Global
Assistant by using ConversationMessageRenderer instead of plain
MessageRenderer. Both agent mode and global mode now have the same
rendering capabilities as AiChatView.
- Change useConversationRenderer default from false to true
- ConversationMessageRenderer provides todo list support and socket
  real-time updates, which should be the standard for all chat views
- Remove redundant explicit useConversationRenderer={true} props
  from GlobalAssistantView and AiChatView
- Update prop documentation to clarify the default behavior
Eliminates the wrapper pattern by merging todo list support and socket
real-time updates directly into the base renderers:

- MessageRenderer now handles both standard and todo_list messages
- CompactMessageRenderer now handles both standard and todo_list messages
- Delete ConversationMessageRenderer.tsx (was wrapper around MessageRenderer)
- Delete CompactConversationMessageRenderer.tsx (was wrapper around CompactMessageRenderer)
- Update ChatMessagesArea to use MessageRenderer directly (remove toggle)
- Update AssistantChatTab to use CompactMessageRenderer directly

This simplifies the architecture by having a single renderer per size
variant (full-size and compact) instead of base + wrapper pattern.
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@2witstudios 2witstudios merged commit 8d69c52 into master Nov 27, 2025
2 checks passed
@2witstudios 2witstudios deleted the claude/refactor-assistant-view-01CppokxNUDJ5A986XKHMMNc branch December 8, 2025 01:26
2witstudios added a commit that referenced this pull request Jan 27, 2026
Zero-trust security hardening across 25 files following defense-in-depth principles.

Fixes by category:
- Path traversal (CWE-022/073): assertPathWithin() containment checks in content-store, upload, computeFileHash
- Prototype pollution (CWE-1321/250): isSafePropertyKey() blocklist, hasOwnProperty.call() guards in content-store, optimize, mcp-tool-converter
- Log injection (CWE-117/134): sanitizeLogValue() + format strings in image-processor, mcp-tool-converter, notification-email-service
- ReDoS (CWE-1333): Bounded quantifiers in mention-processor, safe RFC 5322 email regex in account route
- SSRF prevention (CWE-918): validateRequestUrl() in auth-fetch, hardcoded API URLs in file-processor
- XSS prevention (CWE-079): URL protocol validation in web-preview iframe, offline.html redirect
- Rate limiting (CWE-770): rateLimitUpload middleware on avatar routes
- Origin verification (CWE-346): event.origin check in service worker postMessage handler
- TOCTOU elimination (CWE-367): Atomic readFile replacing stat-then-read in avatar route
- Input validation (CWE-807): Format regex for entryId, agentId, email token, URL construction
- Regex injection (CWE-730): Pattern length limit + try/catch in drive-search-service
- Incomplete sanitization (CWE-116): Full regex metachar escaping in prettier.ts
- Insecure temp files (CWE-377): fs.mkdtemp() in path-validator tests
- Session validation (CWE-073): Type checks + 8KB size limit in auth-storage

Also fixes pre-existing TypeScript error in drive-search-service.ts (RegexSearchResponse type mismatch).

Alerts: #1-75 (73 total, no #49 or #59 in CodeQL)
See CODEQL_ALERT_LOG.md for full remediation details.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2witstudios added a commit that referenced this pull request Jan 27, 2026
* fix(security): remediate all 73 CodeQL vulnerability alerts

Zero-trust security hardening across 25 files following defense-in-depth principles.

Fixes by category:
- Path traversal (CWE-022/073): assertPathWithin() containment checks in content-store, upload, computeFileHash
- Prototype pollution (CWE-1321/250): isSafePropertyKey() blocklist, hasOwnProperty.call() guards in content-store, optimize, mcp-tool-converter
- Log injection (CWE-117/134): sanitizeLogValue() + format strings in image-processor, mcp-tool-converter, notification-email-service
- ReDoS (CWE-1333): Bounded quantifiers in mention-processor, safe RFC 5322 email regex in account route
- SSRF prevention (CWE-918): validateRequestUrl() in auth-fetch, hardcoded API URLs in file-processor
- XSS prevention (CWE-079): URL protocol validation in web-preview iframe, offline.html redirect
- Rate limiting (CWE-770): rateLimitUpload middleware on avatar routes
- Origin verification (CWE-346): event.origin check in service worker postMessage handler
- TOCTOU elimination (CWE-367): Atomic readFile replacing stat-then-read in avatar route
- Input validation (CWE-807): Format regex for entryId, agentId, email token, URL construction
- Regex injection (CWE-730): Pattern length limit + try/catch in drive-search-service
- Incomplete sanitization (CWE-116): Full regex metachar escaping in prettier.ts
- Insecure temp files (CWE-377): fs.mkdtemp() in path-validator tests
- Session validation (CWE-073): Type checks + 8KB size limit in auth-storage

Also fixes pre-existing TypeScript error in drive-search-service.ts (RegexSearchResponse type mismatch).

Alerts: #1-75 (73 total, no #49 or #59 in CodeQL)
See CODEQL_ALERT_LOG.md for full remediation details.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(security): address 6 new CodeQL alerts from initial fix round

Fixes root causes that the first pass missed:

- optimize.ts: Use Map for results instead of user-controlled property keys (alert 78)
- content-store.ts: Use Object.create(null) + isValidPreset() for metadata object (alert 79)
- verify-email/route.ts: Revert unnecessary format check that created a new alert — verifyToken() already validates cryptographically (alert 80)
- web-preview.tsx: Reconstruct URL from parsed.href to break taint chain (alert 76)
- drive-search-service.ts: Escape user pattern for JS line matching — PG handles actual regex (alert 77)
- mcp-tool-converter.ts: Coerce mcpTools.length through Number() to break taint (alert 81)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: update CODEQL_ALERT_LOG with round 2 alert fixes (76-81)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(security): address CodeRabbit review feedback on CodeQL fixes

- optimize.ts: validate presets is array of strings before iterating
- audit-logs/integrity: use centralized isValidId() for CUID2 validation
  instead of hex-only regex pattern
- auth-fetch.ts: block protocol-relative URLs (//evil.com) that bypass
  relative URL allowance
- usePageAgentDashboardStore: use CUID2 format pattern for agent ID
  validation (lowercase letter + lowercase alphanumeric, max 32 chars)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(security): address round 4 CodeRabbit review feedback

- optimize.ts: replace Map<string, any> with strict BatchPresetResult
  union type for type safety
- sw.js: fail-closed origin/source checks - reject empty origin and
  null source instead of allowing them through
- mcp-tool-converter.ts: use RegExp constructor for control char regex
  to satisfy Biome noControlCharactersInRegex rule
- drive-search-service.ts: document that line previews use literal
  matching (escaped for ReDoS prevention) vs PG regex semantics
- CODEQL_ALERT_LOG.md: escape pipe in markdown table regex cell

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(security): validate preset param in serve route before cache lookup

Prevents invalid presets from reaching contentStore.getCache() where
they'd throw and return a generic 500 — now returns proper 400 response.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(security): address code review findings and add unit tests

- Extract IIFE to named sanitizeIframeSrc function for testability
- Apply prototype-safe JSON parsing (Object.create(null)) in getCache
  and cleanupOldCache for consistency with saveCache
- Allow dots in isValidPreset regex for existing presets like
  extracted-text.txt, ocr-text.txt, thumbnail.webp
- Use format string logging in serve.ts to prevent log injection
- Restore original regex pattern for drive search line matching to
  maintain semantic consistency with PostgreSQL regex
- Remove overly restrictive origin allowlist from desktop offline page
  to support localhost and self-hosted app URLs
- Move CODEQL_ALERT_LOG.md and PROGRESS_NOTES.md to docs/security/
- Add 59 unit tests across 4 test files covering isValidPreset,
  isValidContentHash, sanitizeIframeSrc, mention processor regex
  bounds, and AuthFetch URL validation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants