Skip to content

update to main#36

Merged
djanogly merged 1 commit intomainfrom
update/dev-to-main-apr-26
Apr 16, 2026
Merged

update to main#36
djanogly merged 1 commit intomainfrom
update/dev-to-main-apr-26

Conversation

@djanogly
Copy link
Copy Markdown
Contributor

No description provided.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
opencom-landing Ready Ready Preview, Comment Apr 16, 2026 10:25pm
opencom-web Ready Ready Preview, Comment Apr 16, 2026 10:25pm

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Dynamic AI model discovery, vector-based knowledge search, and article link widget integration

✨ Enhancement 🧪 Tests 📝 Documentation 🐞 Bug fix

Grey Divider

Walkthroughs

Description
  **Core Features:**
• Implemented dynamic AI model discovery from gateway with fallback support and timeout handling
• Added vector-based knowledge search with embeddings for semantic relevance in inbox
• Integrated embedding model resolution and compatibility checking across suggestions, embeddings,
  and knowledge modules
• Added article protocol link support (article:<articleId>) in markdown rendering for widget
  navigation
• Implemented embeddings backfill functionality for admin tools
  **AI Agent Improvements:**
• Changed listAvailableModels from static query to dynamic action-based discovery
• Enhanced AI response tracking with model and provider metadata persistence
• Improved model format validation to accept provider-prefixed and raw model IDs
• Added getAIGatewayProviderLabel() utility for flexible provider detection
• Refactored AI settings UI with model discovery fallback and manual entry support
  **Knowledge & Suggestions:**
• Implemented searchWithEmbeddings action for vector-based knowledge search
• Added embedding model tracking in suggestion feedback with embeddingModel field
• Created embedding model compatibility module with normalization and validation
• Updated suggestions panel to display active embedding model
  **Infrastructure & Testing:**
• Upgraded Convex from 1.32.0 to 1.35.1 and Next.js to 15.5.15
• Refactored test admin mutation argument handling to use JSON strings
• Added comprehensive test coverage for AI model discovery, embedding models, and article links
• Created Convex framework guidelines documentation for development patterns
  **UI/UX Enhancements:**
• Added article link click handling in widget messages with data-article-id attribute
• Refactored inbox thread pane layout with improved state management
• Enhanced articles page with embeddings backfill button and feedback display
• Added AI response metadata display (model/provider) in review panel
• Improved Home component config handling with nullish coalescing
  **Security & Documentation:**
• Added undici vulnerability allowlist entries for dev dependencies
• Removed expired testAdmin v.any() exception
• Updated API reference documentation with new AI functions and validation procedures
• Created comprehensive openspec documentation for article link integration and vector search
Diagram
flowchart LR
  A["AI Gateway"] -->|"discover models"| B["listAvailableModels<br/>Action"]
  B -->|"cached results"| C["Settings UI"]
  C -->|"selected model"| D["AI Agent"]
  
  E["Articles"] -->|"embeddings"| F["Vector Search<br/>Action"]
  F -->|"semantic results"| G["Inbox Knowledge"]
  G -->|"article:ID format"| H["Widget Navigation"]
  
  I["Embedding Models<br/>Module"] -->|"resolve & validate"| J["Suggestions"]
  I -->|"resolve & validate"| K["Knowledge Retrieval"]
  I -->|"resolve & validate"| L["Embeddings Generation"]
  
  M["Markdown Parser"] -->|"detect article links"| N["data-article-id<br/>attribute"]
  N -->|"click handler"| H
Loading

Grey Divider

File Changes

1. packages/convex/convex/aiAgent.ts ✨ Enhancement +201/-40

Dynamic AI model discovery and embedding model resolution

• Added imports for embedding model utilities and AI gateway functions
• Introduced new type definitions for AvailableAIModel, OpenAIModelListResponse,
 StoredAIResponse, and ConversationResponse
• Implemented discoverAvailableAIModels() function to fetch models from AI gateway with timeout
 handling
• Added helper functions: normalizeAvailableModelId(), createAvailableAIModel(),
 isLikelyGenerationModel(), dedupeAvailableAIModels()
• Changed listAvailableModels from static query to dynamic authAction that discovers models from
 gateway
• Updated updateSettings mutation to use resolveContentEmbeddingModel() for embedding model
 normalization
• Added explicit return type annotations to mutation and query handlers
• Modified getConversationResponses to filter responses with messageId and restructure response
 context

packages/convex/convex/aiAgent.ts


2. packages/convex/tests/aiAgentRuntimeSafety.test.ts 🧪 Tests +116/-12

Enhanced AI model discovery and validation testing

• Added afterEach hook to clean up global stubs
• Updated test imports to use definition references with type casting for handler access
• Modified model format validation tests to accept provider-prefixed and raw model IDs
• Added test for filtering non-generation models and preserving selected model fallback
• Updated environment setup to include AI_GATEWAY_BASE_URL
• Changed test model format from invalid-model-format to invalid/model/format

packages/convex/tests/aiAgentRuntimeSafety.test.ts


3. apps/web/src/app/settings/hooks/useSettingsSectionsConvex.ts ✨ Enhancement +140/-39

Refactor AI settings to use action-based model discovery

• Added type definitions for AI agent settings, available models, and update arguments
• Changed AVAILABLE_MODELS_QUERY_REF to AVAILABLE_MODELS_ACTION_REF (query to action)
• Updated UPDATE_AI_SETTINGS_REF return type from null to Id<"aiAgentSettings">
• Implemented useEffect hook to load available models with debouncing and cancellation
• Added saveSettings callback function with error handling and loading state
• Exposed availableModelsStatus and isSaving state in return object

apps/web/src/app/settings/hooks/useSettingsSectionsConvex.ts


View more (74)
4. packages/convex/convex/suggestions.ts ✨ Enhancement +36/-14

Integrate embedding model resolution and tracking

• Imported DEFAULT_CONTENT_EMBEDDING_MODEL and resolveContentEmbeddingModel from new embedding
 models module
• Removed local DEFAULT_EMBEDDING_MODEL constant
• Added embeddingModel field to SuggestionResult type
• Updated searchSimilar and searchSimilarInternal to use resolveContentEmbeddingModel()
• Modified getForConversation to include embeddingModel in returned results
• Added embeddingModel parameter to trackUsage and trackDismissal mutations
• Updated getContentById to return slug field for articles
• Changed embedding model reference in searchForWidget to use constant

packages/convex/convex/suggestions.ts


5. packages/convex/convex/aiAgentActions.ts ✨ Enhancement +40/-26

Support flexible AI model format and gateway provider detection

• Added import for getAIGatewayProviderLabel from AI gateway module
• Removed SUPPORTED_AI_PROVIDERS set constant
• Updated parseModel() to use getAIGatewayProviderLabel() for default provider
• Enhanced getAIConfigurationDiagnostic() to accept aiGatewayProviderLabel parameter
• Relaxed model format validation to accept raw model IDs and provider-prefixed formats
• Added maybeGetShallowRunAction() helper function for optional action context
• Updated knowledge retrieval to check if runAction exists before calling

packages/convex/convex/aiAgentActions.ts


6. packages/convex/convex/knowledge.ts ✨ Enhancement +137/-3

Add vector-based knowledge search with embeddings

• Added imports for embedding functionality and AI client creation
• Implemented getShallowRunQuery() helper function for type-safe query calls
• Added searchWithEmbeddings action for vector-based knowledge search with embedding
• Implemented deduplication and content filtering logic for search results
• Added formatting improvements to multi-line function calls

packages/convex/convex/knowledge.ts


7. packages/convex/tests/suggestionsMetadataSemantics.test.ts 🧪 Tests +117/-0

Test embedding model persistence in suggestion feedback

• New test file for suggestion feedback metadata semantics
• Tests verify that embeddingModel is persisted in suggestion usage and dismissal feedback
• Mocks database operations and permission checks
• Validates feedback records contain correct embedding model information

packages/convex/tests/suggestionsMetadataSemantics.test.ts


8. apps/web/src/app/inbox/hooks/useInboxConvex.ts ✨ Enhancement +38/-11

Migrate knowledge search to action-based implementation

• Changed KNOWLEDGE_SEARCH_QUERY_REF from query to KNOWLEDGE_SEARCH_ACTION_REF action
• Implemented useEffect hook for knowledge search with debouncing (300ms)
• Added state management for knowledge results and cancellation handling
• Removed direct query call, replaced with action-based search

apps/web/src/app/inbox/hooks/useInboxConvex.ts


9. apps/web/src/app/articles/hooks/useArticlesAdminConvex.ts ✨ Enhancement +20/-8

Add embeddings backfill action to admin tools

• Added imports for useWebAction and webActionRef
• Added type definitions for BackfillEmbeddingsArgs and BackfillEmbeddingsResult
• Created BACKFILL_EMBEDDINGS_REF action reference
• Exposed backfillEmbeddings action in return object
• Reformatted multi-line query calls for consistency

apps/web/src/app/articles/hooks/useArticlesAdminConvex.ts


10. packages/web-shared/src/markdown.ts ✨ Enhancement +38/-10

Support article protocol links in markdown parsing

• Added data-article-id to ALLOWED_ATTR list for sanitization
• Implemented isArticleLink() and extractArticleId() helper functions
• Enhanced enforceSafeLinksAndMedia() to detect and process article protocol links
• Added opencom-article-link CSS class assignment for article links
• Updated DOMPurify configuration with custom ALLOWED_URI_REGEXP to allow article protocol
• Added tests for article link detection, rendering, and invalid format handling

packages/web-shared/src/markdown.ts


11. packages/convex/convex/lib/aiGateway.ts ✨ Enhancement +63/-6

Extract AI gateway configuration into reusable utilities

• Added constants for default OpenAI and Vercel AI Gateway base URLs
• Implemented getAIGatewayApiKey() to safely retrieve and trim API key
• Implemented getAIBaseURL() to determine base URL from environment or API key type
• Implemented getAIGatewayProviderLabel() to extract provider name from base URL
• Added sanitizeProviderLabel() helper for normalizing provider names
• Updated createAIClient() to use new helper functions

packages/convex/convex/lib/aiGateway.ts


12. packages/convex/tests/aiAgentAuthorizationSemantics.test.ts 🧪 Tests +20/-1

Update authorization tests for AI response metadata

• Updated imports to use definition references with type casting for handler access
• Added messageId, sources, handedOff, model, and provider fields to test response objects
• Added assertions to verify model and provider fields are preserved in responses

packages/convex/tests/aiAgentAuthorizationSemantics.test.ts


13. packages/convex/convex/embeddings.ts ✨ Enhancement +5/-3

Integrate embedding model resolution and fix permissions

• Imported DEFAULT_CONTENT_EMBEDDING_MODEL and resolveContentEmbeddingModel from embedding
 models module
• Removed local DEFAULT_EMBEDDING_MODEL constant
• Updated generateInternal to use resolveContentEmbeddingModel() for model normalization
• Changed backfillExisting permission from articles.read to articles.publish

packages/convex/convex/embeddings.ts


14. packages/convex/tests/embeddingModels.test.ts 🧪 Tests +42/-0

Test embedding model compatibility and normalization

• New test file for content embedding model compatibility
• Tests verify model normalization, fallback behavior, and index compatibility
• Validates that incompatible large embeddings fall back to default model
• Tests case-insensitive model name normalization

packages/convex/tests/embeddingModels.test.ts


15. packages/convex/convex/lib/embeddingModels.ts ✨ Enhancement +45/-0

Create embedding model compatibility and resolution module

• New module for embedding model management and compatibility
• Exported constants: CONTENT_EMBEDDING_INDEX_DIMENSIONS, DEFAULT_CONTENT_EMBEDDING_MODEL,
 LARGE_CONTENT_EMBEDDING_MODEL, LEGACY_CONTENT_EMBEDDING_MODEL
• Implemented resolveContentEmbeddingModel() to normalize and validate embedding models
• Implemented isContentEmbeddingModelSupportedByCurrentIndex() for compatibility checking
• Implemented getContentEmbeddingModelCompatibilityMessage() for user-friendly error messages

packages/convex/convex/lib/embeddingModels.ts


16. packages/convex/convex/testAdmin.ts ✨ Enhancement +22/-3

Refactor test admin mutation argument handling

• Added parseMutationArgsJson() function to parse JSON mutation arguments
• Changed runTestMutation argument from mutationArgs to mutationArgsJson string
• Updated handler to parse JSON string instead of accepting object directly

packages/convex/convex/testAdmin.ts


17. packages/convex/tests/aiAgent.test.ts 🧪 Tests +15/-1

Update AI agent tests for action-based model listing

• Updated listAvailableModels test to call action instead of query with workspace ID
• Added assertions for model and provider fields in AI responses
• Added test to verify selected model is preserved when discovery falls back

packages/convex/tests/aiAgent.test.ts


18. packages/convex/convex/aiAgentActionsKnowledge.ts ✨ Enhancement +4/-2

Integrate embedding model resolution in knowledge retrieval

• Imported DEFAULT_CONTENT_EMBEDDING_MODEL and resolveContentEmbeddingModel from embedding
 models module
• Removed local DEFAULT_EMBEDDING_MODEL constant
• Updated getRelevantKnowledgeForRuntimeAction to use resolveContentEmbeddingModel() for model
 normalization

packages/convex/convex/aiAgentActionsKnowledge.ts


19. packages/web-shared/src/markdown.test.ts 🧪 Tests +25/-0

Test article protocol link handling in markdown

• Added test for article link detection with data-article-id attribute
• Added test for article link text rendering
• Added test for invalid article link format handling
• Added test to prevent article protocol in image src attributes

packages/web-shared/src/markdown.test.ts


20. packages/convex/tests/runtimeTypeHardeningGuard.test.ts 🧪 Tests +14/-0

Add type hardening validation for knowledge module

• Added knowledge.ts to target files list for type hardening validation
• Added test to verify knowledge module uses fixed typed refs and getShallowRunQuery

packages/convex/tests/runtimeTypeHardeningGuard.test.ts


21. packages/convex/convex/_generated/api.d.ts ⚙️ Configuration changes +2/-0

Register embedding models module in API types

• Added import for lib_embeddingModels module
• Registered embedding models module in API type definitions

packages/convex/convex/_generated/api.d.ts


22. packages/convex/tests/suggestions.test.ts 🧪 Tests +14/-0

Test embedding model tracking in suggestions

• Added embeddingModel parameter to trackUsage and trackDismissal test calls
• Added assertions to verify embeddingModel is persisted in feedback records

packages/convex/tests/suggestions.test.ts


23. packages/convex/convex/schema/operationsAiTables.ts ✨ Enhancement +3/-1

Use embedding dimension constant and track model in feedback

• Imported CONTENT_EMBEDDING_INDEX_DIMENSIONS from embedding models module
• Replaced hardcoded dimension value (1536) with constant
• Added optional embeddingModel field to suggestionFeedback table

packages/convex/convex/schema/operationsAiTables.ts


24. apps/web/src/components/hooks/useSuggestionsPanelConvex.ts ✨ Enhancement +3/-1

Add embedding model tracking to suggestions panel

• Added embeddingModel field to SuggestionRecord type
• Added embeddingModel parameter to TrackSuggestionArgs type
• Updated AI_SETTINGS_QUERY_REF to include embeddingModel field

apps/web/src/components/hooks/useSuggestionsPanelConvex.ts


25. packages/convex/convex/testing/helpers/ai.ts 🧪 Tests +14/-0

Add test helper for listing suggestion feedback

• Added listTestSuggestionFeedback internal mutation for test helpers
• Exported new helper in aiTestHelpers object

packages/convex/convex/testing/helpers/ai.ts


26. packages/convex/convex/testing/helpers.ts 🧪 Tests +2/-0

Export suggestion feedback test helper

• Exported listTestSuggestionFeedback from AI test helpers

packages/convex/convex/testing/helpers.ts


27. packages/convex/convex/schema/operationsReportingTables.ts ✨ Enhancement +2/-1

Make messageId optional and add attempt status tracking

• Changed messageId field from required to optional in aiResponses table
• Added optional attemptStatus field to aiResponses table

packages/convex/convex/schema/operationsReportingTables.ts


28. apps/web/e2e/helpers/test-data.ts ✨ Enhancement +5/-1

Update test data helper for JSON mutation arguments

• Updated callInternalMutation to pass mutationArgsJson as JSON string instead of object

apps/web/e2e/helpers/test-data.ts


29. apps/web/e2e/helpers/widget-helpers.ts 🐞 Bug fix +2/-0

Dismiss tour before NPS rating submission

• Added dismissTour() call before NPS rating submission in submitNPSRating()

apps/web/e2e/helpers/widget-helpers.ts


30. apps/web/src/app/inbox/inboxRenderTypes.ts ✨ Enhancement +2/-0

Add model and provider fields to AI response type

• Added model and provider fields to InboxAiResponse interface

apps/web/src/app/inbox/inboxRenderTypes.ts


31. apps/web/e2e/global-teardown.ts ✨ Enhancement +1/-1

Update global teardown for JSON mutation arguments

• Updated runTestMutation call to pass mutationArgsJson as JSON string

apps/web/e2e/global-teardown.ts


32. packages/convex/tests/setupTestAdminFallback.ts ✨ Enhancement +1/-1

Update test admin fallback for JSON mutation arguments

• Updated callInternalTestMutation to pass mutationArgsJson as JSON string

packages/convex/tests/setupTestAdminFallback.ts


33. packages/convex/convex/schema/inboxConversationTables.ts ✨ Enhancement +1/-0

Add AI turn sequence tracking to conversations

• Added optional aiTurnSequence field to conversations table for tracking AI interaction sequence

packages/convex/convex/schema/inboxConversationTables.ts


34. packages/convex/tests/helpers/testHelpers.ts ✨ Enhancement +1/-1

Update test helpers for JSON mutation arguments

• Updated callInternalTestMutation to pass mutationArgsJson as JSON string

packages/convex/tests/helpers/testHelpers.ts


35. scripts/screenshots/seed.ts ✨ Enhancement +1/-1

Update screenshot seed script for JSON mutation arguments

• Updated callMutation to pass mutationArgsJson as JSON string

scripts/screenshots/seed.ts


36. apps/widget/src/styles.css Formatting +184/-47

Format CSS and add article link styling

• Reformatted multi-line CSS properties for improved readability
• Added .opencom-article-link class with blue color and underline styling
• Updated multiple transition and box-shadow properties to use multi-line format

apps/widget/src/styles.css


37. convex/_generated/ai/guidelines.md 📝 Documentation +365/-0

Add comprehensive Convex framework guidelines

• New comprehensive Convex framework guidelines document
• Covers function registration, validators, authentication, schema design, testing, and more
• Includes code examples for common patterns and best practices

convex/_generated/ai/guidelines.md


38. apps/web/src/app/inbox/page.tsx ✨ Enhancement +13/-10

Update article link format and code formatting

• Reformatted handleOpenConversationFromNotification callback for readability
• Changed article link insertion from /help/{slug} format to article:{id} protocol format

apps/web/src/app/inbox/page.tsx


39. pnpm-lock.yaml Dependencies +150/-145

Dependency updates for Convex, Next.js, and Vite

• Updated convex from 1.32.0 to 1.35.1 across multiple workspace entries
• Upgraded next from 15.5.12 to 15.5.15 with corresponding SWC compiler updates
• Updated vite from 7.3.1 to 7.3.2 and related plugin dependencies
• Added package overrides for @xmldom/xmldom, fast-xml-parser, flatted, node-forge, and
 picomatch versions
• Updated geist dependency to use the newer Next.js version

pnpm-lock.yaml


40. apps/web/src/app/inbox/InboxThreadPane.tsx ✨ Enhancement +385/-387

Refactor inbox thread pane layout and state management

• Reformatted function signature for onInsertKnowledgeContent to single line
• Changed article knowledge item layout from horizontal (flex items-center gap-2) to vertical
 (flex flex-col gap-1)
• Reorganized header section with improved indentation and moved AI handoff banner before compact
 viewport actions
• Refactored compact viewport panel state to use activeCompactPanel instead of separate boolean
 flags
• Restructured knowledge picker and message input sections with consistent indentation

apps/web/src/app/inbox/InboxThreadPane.tsx


41. apps/web/src/app/articles/page.tsx ✨ Enhancement +64/-19

Add embeddings backfill functionality to articles page

• Added import for RefreshCw icon from lucide-react
• Added state management for embeddings backfill operation (isBackfillingEmbeddings,
 backfillNotice, backfillError)
• Implemented handleBackfillEmbeddings function to trigger embeddings refresh with result feedback
• Added "Refresh Embeddings" button with role-based access control (owner/admin only)
• Reorganized action buttons layout into flex column with separate rows for embeddings and article
 creation buttons
• Added success and error message display for backfill operations

apps/web/src/app/articles/page.tsx


42. apps/web/src/app/settings/AIAgentSection.tsx ✨ Enhancement +45/-24

Enhance AI model selection with discovery fallback

• Added normalizeModelValue utility function to trim model input
• Updated hook to return availableModelsStatus, isSaving, and saveSettings instead of
 updateSettings
• Added computed properties for selected discovered model and placeholder text based on discovery
 status
• Refactored model selection UI to include both dropdown and manual text input field
• Added error message display when model discovery is unavailable
• Updated help text to clarify manual model ID entry and AI gateway interpretation

apps/web/src/app/settings/AIAgentSection.tsx


43. apps/widget/src/components/conversationView/MessageList.tsx ✨ Enhancement +31/-3

Add article link click handling to widget messages

• Added handleMessageClick function to detect and handle article link clicks via data-article-id
 attribute
• Attached click handler to message content div to enable in-widget article navigation
• Improved code formatting with consistent line breaks for readability
• Added aria-label to dismiss button for accessibility

apps/widget/src/components/conversationView/MessageList.tsx


44. package.json Dependencies +10/-1

Update Convex and add package overrides

• Updated convex from ^1.32.0 to 1.35.1 (pinned version)
• Added pnpm overrides for multiple packages including @xmldom/xmldom, fast-xml-parser,
 flatted, node-forge, picomatch, and vite

package.json


45. apps/web/src/app/settings/AIAgentSection.test.tsx 🧪 Tests +87/-0

Add tests for AI model discovery fallback

• New test file for AIAgentSection component
• Tests model discovery fallback behavior when discovery fails
• Verifies placeholder text transitions from "Loading" to "unavailable" state
• Confirms error message displays when model discovery fails

apps/web/src/app/settings/AIAgentSection.test.tsx


46. apps/web/src/components/SuggestionsPanel.tsx ✨ Enhancement +14/-0

Add embedding model tracking and visibility

• Added resolvedEmbeddingModel computed property to display active embedding model
• Updated trackUsage and trackDismissal calls to include embeddingModel parameter
• Added display of embedding model in suggestions panel UI with data-testid
• Added per-suggestion embedding model display in suggestion items
• Added aria-label to dismiss button for accessibility

apps/web/src/components/SuggestionsPanel.tsx


47. docs/api-reference.md 📝 Documentation +53/-2

Document AI agent API and model validation procedures

• Expanded AI Agent API reference table with new functions: getPublicSettings,
 getConversationResponses, listAvailableModels
• Added comprehensive documentation for dual model settings (reply generation vs.
 suggestions/embedding)
• Added validation procedures for reply generation model and suggestions embedding model
• Documented admin UI visibility for AI review panel and suggestions panel with model metadata

docs/api-reference.md


48. openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/shared-markdown-rendering-sanitization/spec.md 📝 Documentation +44/-0

Add specification for shared markdown rendering

• New specification document for shared markdown rendering implementation
• Defines requirements for web and widget to consume shared markdown rendering utility
• Specifies article link detection with article: protocol and data-article-id attribute
• Documents in-widget article navigation behavior and click handling

openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/shared-markdown-rendering-sanitization/spec.md


49. apps/mobile/package.json Dependencies +1/-1

Update Convex dependency in mobile app

• Updated convex from ^1.32.0 to 1.35.1 (pinned version)

apps/mobile/package.json


50. apps/web/src/components/SuggestionsPanel.test.tsx 🧪 Tests +95/-0

Add comprehensive tests for SuggestionsPanel component

• New test file for SuggestionsPanel component with 95 lines of test coverage
• Tests verify embedding model display and tracking for usage and dismissal events
• Mocks useSuggestionsPanelConvex hook and tests user interactions with insert/dismiss buttons
• Validates that embedding model is passed correctly to tracking functions

apps/web/src/components/SuggestionsPanel.test.tsx


51. openspec/changes/archive/2026-03-13-article-link-widget-integration/design.md 📝 Documentation +79/-0

Design article link widget integration and vector search

• New design document for article link widget integration feature
• Documents decision to use article:<articleId> format for article links instead of /help/slug
• Details widget article link detection via shared markdown utility with data-article-id attribute
• Outlines inbox knowledge search vector search implementation and identifies risks/trade-offs

openspec/changes/archive/2026-03-13-article-link-widget-integration/design.md


52. security/dependency-audit-allowlist.json Security +48/-0

Add undici vulnerability allowlist entries for dev dependencies

• Adds 6 new allowlist entries for undici module vulnerabilities (IDs 1114591, 1114592, 1114637,
 1114638, 1114639, 1114640)
• All entries marked as transitive dev dependencies through wrangler -> miniflare for Cloudflare
 Workers
• Entries expire on 2026-06-30 with cleanup criteria tied to miniflare/wrangler upgrades
• WebSocket vulnerabilities noted as only affecting dev environment

security/dependency-audit-allowlist.json


53. openspec/specs/inbox-knowledge-insertion/spec.md 📝 Documentation +23/-5

Update inbox knowledge insertion spec with article link format

• Adds blank lines after section headers for improved formatting
• Splits article insertion scenario into two distinct scenarios: "insert article link" and "insert
 article content"
• Updates article link format to [title](article:<articleId>) with article ID for widget
 navigation
• Clarifies that article content insertion is separate from link insertion workflow

openspec/specs/inbox-knowledge-insertion/spec.md


54. openspec/changes/archive/2026-03-13-article-link-widget-integration/tasks.md 📝 Documentation +46/-0

Document article link integration implementation tasks

• New tasks file documenting 6 major implementation areas with completed checkboxes
• Backend tasks cover vector search query creation and embedding integration
• Web inbox tasks address knowledge search integration and article link format changes
• Shared markdown and widget tasks detail article link detection and click handling
• Verification section includes typecheck, tests, and manual testing tasks

openspec/changes/archive/2026-03-13-article-link-widget-integration/tasks.md


55. apps/web/src/app/inbox/InboxAiReviewPanel.test.tsx 🧪 Tests +46/-0

Add tests for InboxAiReviewPanel metadata rendering

• New test file for InboxAiReviewPanel component with 46 lines
• Tests rendering of persisted model and provider metadata for AI responses
• Validates display of model identifier (e.g., openai/gpt-5-nano) and provider name
• Uses type-safe ID helpers for message and response IDs

apps/web/src/app/inbox/InboxAiReviewPanel.test.tsx


56. openspec/changes/archive/2026-03-13-article-link-widget-integration/proposal.md 📝 Documentation +30/-0

Propose article link widget integration feature

• New proposal document explaining article link widget integration feature
• Describes article link format change from /help/slug to article:<articleId> for widget
 navigation
• Lists new and modified capabilities including vector search and markdown rendering changes
• Maps impact to specific files across inbox, widget, shared, and convex packages

openspec/changes/archive/2026-03-13-article-link-widget-integration/proposal.md


57. apps/widget/src/components/Home.tsx ✨ Enhancement +6/-5

Improve Home component config handling with defaults

• Refactors homeConfig assignment to use nullish coalescing operator with getDefaultHomeConfig()
• Reformats multi-line query assignment for better readability
• Changes homeConfig?.enabled check to homeConfig.enabled since config is now guaranteed
 non-null

apps/widget/src/components/Home.tsx


58. openspec/specs/shared-markdown-rendering-sanitization/spec.md 📝 Documentation +18/-0

Add article link detection requirement to markdown spec

• Adds blank lines after section headers for formatting consistency
• Adds new requirement for article link detection with article: protocol format
• Documents data-article-id attribute emission and prevention of target="_blank" for article
 links
• Specifies widget click handler behavior for article link navigation

openspec/specs/shared-markdown-rendering-sanitization/spec.md


59. openspec/specs/inbox-knowledge-vector-search/spec.md 📝 Documentation +33/-0

Create inbox knowledge vector search specification

• New specification file for inbox knowledge vector search feature
• Defines requirement for vector search with embeddings for semantic relevance
• Documents scenarios for semantic query search and mixed content type results
• Specifies workspace filtering requirement at vector search level

openspec/specs/inbox-knowledge-vector-search/spec.md


60. openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/inbox-knowledge-insertion/spec.md 📝 Documentation +24/-0

Archive modified inbox knowledge insertion requirements

• New archived spec documenting modified requirements for knowledge insertion
• Details article link format change to [title](article:<articleId>) with article ID
• Separates article link insertion from article content insertion scenarios
• Specifies picker closure behavior after insertion actions

openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/inbox-knowledge-insertion/spec.md


61. apps/web/package.json Dependencies +2/-2

Update convex and next package versions

• Updates convex dependency from ^1.32.0 to 1.35.1 (pinned version)
• Updates next dependency from ^15.5.10 to ^15.5.15 (patch version bump)

apps/web/package.json


62. openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/inbox-knowledge-vector-search/spec.md 📝 Documentation +27/-0

Archive inbox knowledge vector search requirements

• New archived spec documenting added requirements for vector search
• Details semantic relevance search with embeddings for articles and snippets
• Documents mixed content type results with relevance scoring
• Specifies workspace filtering at vector search level

openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/inbox-knowledge-vector-search/spec.md


63. convex/_generated/ai/ai-files.state.json ⚙️ Configuration changes +13/-0

Add Convex AI files state configuration

• New generated state file for Convex AI configuration
• Contains hash values for guidelines, agents, and Claude documentation
• Lists installed Convex agent skills for common tasks

convex/_generated/ai/ai-files.state.json


64. AGENTS.md 📝 Documentation +9/-0

Add Convex guidelines and CI check instructions

• Adds instruction to run pnpm ci:check at end of proposals before PR submission
• Adds new section with Convex project guidelines and AI file information
• References convex/_generated/ai/guidelines.md for Convex API patterns
• Documents Convex agent skills installation command

AGENTS.md


65. apps/web/src/app/inbox/InboxAiReviewPanel.tsx ✨ Enhancement +6/-0

Display AI model and provider metadata in review panel

• Adds two new metadata display spans for AI response model and provider information
• Uses data-testid attributes for test identification with response ID
• Displays model identifier (e.g., openai/gpt-5-nano) and provider name in UI
• Maintains consistent styling with existing confidence and feedback badges

apps/web/src/app/inbox/InboxAiReviewPanel.tsx


66. apps/landing/package.json Dependencies +1/-1

Update next package version

• Updates next dependency from ^15.5.10 to ^15.5.15 (patch version bump)

apps/landing/package.json


67. ROADMAP.md 📝 Documentation +3/-1

Add web admin and AI agent improvements to roadmap

• Adds three new roadmap items for web admin improvements
• Items include multi-line chat input field with scrollbar, expandable settings headers, and AI
 agent evals/traces
• Maintains existing roadmap structure and formatting

ROADMAP.md


68. apps/widget/package.json Dependencies +1/-1

Update convex package version

• Updates convex dependency from ^1.32.0 to 1.35.1 (pinned version)

apps/widget/package.json


69. openspec/specs/ai-help-center-linked-sources/spec.md 📝 Documentation +11/-0

Add article link format consistency requirement to sources spec

• Adds blank line after Purpose section header for formatting consistency
• Adds new requirement for article links to use consistent format with AI sources
• Documents article link format using article ID instead of slug for widget navigation
• Specifies that agent-inserted links should open in widget like AI source links

openspec/specs/ai-help-center-linked-sources/spec.md


70. security/convex-v-any-arg-exceptions.json Security +1/-13

Remove expired testAdmin v.any() exception

• Removes single exception entry for packages/convex/convex/testAdmin.ts handler
• Clears entries array to empty list, indicating exception is no longer needed
• Maintains file structure with version and description fields

security/convex-v-any-arg-exceptions.json


71. openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/ai-help-center-linked-sources/spec.md 📝 Documentation +11/-0

Archive article link format consistency requirement

• New archived spec documenting added requirement for article link format consistency
• Specifies article links use article ID-based format matching AI sources
• Documents agent-inserted article link navigation behavior in widget

openspec/changes/archive/2026-03-13-article-link-widget-integration/specs/ai-help-center-linked-sources/spec.md


72. CLAUDE.md 📝 Documentation +7/-0

Create Claude AI guidelines for Convex development

• New file with Convex project guidelines for Claude AI
• References convex/_generated/ai/guidelines.md for Convex API patterns and rules
• Documents Convex agent skills installation command
• Mirrors content from AGENTS.md for AI assistant context

CLAUDE.md


73. packages/convex/package.json Dependencies +1/-1

Update convex package version

• Updates convex dependency from ^1.32.0 to 1.35.1 (pinned version)

packages/convex/package.json


74. packages/react-native-sdk/package.json Dependencies +1/-1

Update convex package version

• Updates convex dependency from ^1.32.0 to 1.35.1 (pinned version)

packages/react-native-sdk/package.json


75. packages/sdk-core/package.json Dependencies +1/-1

Update convex package version

• Updates convex dependency from ^1.32.0 to 1.35.1 (pinned version)

packages/sdk-core/package.json


76. openspec/changes/archive/2026-03-13-article-link-widget-integration/.openspec.yaml ⚙️ Configuration changes +2/-0

Add openspec metadata for article link integration

• New metadata file for archived change specification
• Specifies schema type as spec-driven
• Documents creation date as 2026-03-13

openspec/changes/archive/2026-03-13-article-link-widget-integration/.openspec.yaml


77. apps/web/next.config.js Additional files +0/-12

...

apps/web/next.config.js


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 16, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. CLAUDE.md uses npx 📘 Rule violation § Compliance
Description
The new CLAUDE.md instructs running npx convex ai-files install, which violates the requirement
to use pnpm for package management/CLI execution. This introduces non-standard tooling guidance
for the repo.
Code

CLAUDE.md[6]

+Convex agent skills for common tasks can be installed by running `npx convex ai-files install`.
Evidence
PR Compliance ID 54502 requires using pnpm commands; npx usage in changed documentation is
explicitly disallowed. CLAUDE.md adds a command using npx.

Rule 54502: Use PNPM exclusively for package management commands
CLAUDE.md[1-7]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CLAUDE.md` includes a `npx` command (`npx convex ai-files install`), which violates the repo’s PNPM-only rule.

## Issue Context
Docs are included in the compliance scan; guidance must not recommend `npx`/`npm`/`yarn` when `pnpm` alternatives exist.

## Fix Focus Areas
- CLAUDE.md[1-7]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. GET_AI_SETTINGS_REF string ref 📘 Rule violation ⌂ Architecture
Description
GET_AI_SETTINGS_REF is created via makeFunctionReference("suggestions:getAiSettings") even
though generated internal refs are available. This violates the required ordering for Convex
backend function references and bypasses codegen-based correctness guarantees.
Code

packages/convex/convex/suggestions.ts[R128-135]

const GET_AI_SETTINGS_REF: SuggestionQueryRef<
  { workspaceId: Id<"workspaces"> },
  Doc<"aiAgentSettings"> | null
-> = makeFunctionReference<"query", { workspaceId: Id<"workspaces"> }, Doc<"aiAgentSettings"> | null>(
-  "suggestions:getAiSettings"
-);
+> = makeFunctionReference<
+  "query",
+  { workspaceId: Id<"workspaces"> },
+  Doc<"aiAgentSettings"> | null
+>("suggestions:getAiSettings");
Evidence
PR Compliance ID 96849 requires generated api/internal refs to be used when available, with
makeFunctionReference only as a fallback. The changed code uses makeFunctionReference for
getAiSettings, which is exported as an internalQuery, and generated internal refs exist for
the suggestions module.

Rule 96849: Standardize Convex backend function reference boundaries ordering
packages/convex/convex/suggestions.ts[128-135]
packages/convex/convex/_generated/api.d.ts[392-403]
packages/convex/convex/_generated/api.d.ts[131-133]
packages/convex/convex/suggestions.ts[613-623]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`suggestions.ts` defines `GET_AI_SETTINGS_REF` using `makeFunctionReference("suggestions:getAiSettings")` even though a generated `internal` ref should be used.

## Issue Context
The backend reference ordering requires using generated refs first to avoid string drift and to keep references aligned with Convex codegen.

## Fix Focus Areas
- packages/convex/convex/suggestions.ts[128-135]
- packages/convex/convex/_generated/api.d.ts[392-403]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Vector search query fan-out 🐞 Bug ➹ Performance
Description
knowledge:searchWithEmbeddings performs limit * 8 vector search and then does Promise.all
runQuery calls per match; at the UI default (limit=20) this can trigger ~160 internal queries per
search and risks slowdowns/timeouts.
Code

packages/convex/convex/knowledge.ts[R284-299]

+    const vectorResults = await ctx.vectorSearch("contentEmbeddings", "by_embedding", {
+      vector: embedding,
+      limit: limit * 8,
+      filter: (q) => q.eq("workspaceId", args.workspaceId),
+    });
+
+    const contentTypeSet =
+      args.contentTypes && args.contentTypes.length > 0 ? new Set(args.contentTypes) : null;
+
+    const embeddingDocs = await Promise.all(
+      vectorResults.map((result) =>
+        runQuery(internal.suggestions.getEmbeddingById, { id: result._id }).then((doc) =>
+          doc ? { ...doc, _score: result._score } : null
+        )
+      )
+    );
Evidence
The action requests 8x the needed results and then fetches each embedding doc via a separate
internal query in parallel, and the inbox UI calls this action repeatedly on search term changes
(debounced). This combination can create large bursts of internal calls and latency spikes under
normal usage.

packages/convex/convex/knowledge.ts[284-338]
apps/web/src/app/inbox/hooks/useInboxConvex.ts[181-207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`knowledge:searchWithEmbeddings` does a vectorSearch with `limit * 8` and then performs one internal `runQuery` per vector result to fetch the embedding doc. With the inbox default limit (20), this becomes ~160 internal calls per search, which is likely to cause slow actions and/or timeouts.

### Issue Context
The fan-out happens even though only `limit` deduped results are ultimately returned.

### Fix Focus Areas
- packages/convex/convex/knowledge.ts[284-338]
- apps/web/src/app/inbox/hooks/useInboxConvex.ts[181-207]

### Implementation notes
- Reduce the `limit * 8` multiplier (or make it adaptive) to minimize worst-case work.
- Introduce a single internal query like `internal.suggestions.getEmbeddingsByIds({ ids: Id<"contentEmbeddings">[] })` to fetch embedding docs in batch.
- Consider an internal query that directly returns the minimal fields needed (contentType/contentId/title/snippet/updatedAt) for a list of embedding ids to avoid repeated round-trips.
- If batching isn’t feasible, at least cap concurrency and/or stop fetching once enough deduped results are found.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Unvalidated article-id click 🐞 Bug ☼ Reliability
Description
The widget treats any clicked element with [data-article-id] as an article link and casts the
attribute value to Id<"articles"> without validation; because shared markdown allows raw HTML and
now allows data-article-id, crafted message content can trigger Convex v.id("articles") argument
validation errors at runtime.
Code

apps/widget/src/components/conversationView/MessageList.tsx[R74-90]

+  const handleMessageClick = (event: React.MouseEvent<HTMLDivElement>) => {
+    const target = event.target;
+    if (!target) {
+      return;
+    }
+    const element = target instanceof Element ? target : (target as Text).parentElement;
+    if (!element) {
+      return;
+    }
+    const articleLink = element.closest("[data-article-id]");
+    if (articleLink) {
+      event.preventDefault();
+      event.stopPropagation();
+      const articleId = articleLink.getAttribute("data-article-id");
+      if (articleId) {
+        onSelectArticle(articleId as Id<"articles">);
+      }
Evidence
Shared markdown rendering enables raw HTML (html: true) and allows data-article-id as a
sanitized attribute. The widget click handler looks for the attribute on any element and passes it
to article selection without validating it’s a real Convex article id. The Convex query used for
visitor article fetch requires args.id: v.id("articles"), so invalid strings will throw before the
handler runs, producing a client-visible error.

packages/web-shared/src/markdown.ts[4-35]
packages/web-shared/src/markdown.ts[92-139]
apps/widget/src/components/conversationView/MessageList.tsx[74-91]
apps/widget/src/components/ConversationView.tsx[437-447]
packages/convex/convex/articles.ts[1146-1153]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The widget click handler opens an article for any element matching `[data-article-id]` and casts the attribute to `Id<"articles">` without runtime validation. Because shared markdown supports raw HTML and now allows `data-article-id` through sanitization, a crafted message can inject an invalid `data-article-id` and cause Convex `v.id("articles")` argument validation errors when the widget tries to fetch the article.

### Issue Context
- `@opencom/web-shared` markdown uses `MarkdownIt({ html: true })`.
- DOMPurify allows `data-article-id`.
- The click handler matches `[data-article-id]` regardless of whether the element is a validated `article:` link.

### Fix Focus Areas
- packages/web-shared/src/markdown.ts[4-35]
- packages/web-shared/src/markdown.ts[92-139]
- apps/widget/src/components/conversationView/MessageList.tsx[74-91]

### Implementation notes
- In `enforceSafeLinksAndMedia`, proactively remove `data-article-id` from all elements/anchors by default, and only set it when the href is a validated `article:<id>` link.
- In the widget click handler, validate `articleId` before calling `onSelectArticle` (e.g., ensure it matches the same strict format you generate/accept for article ids) and ignore clicks when invalid.
- Optionally scope the selector to anchors only (e.g., `closest('a[data-article-id]')`) to reduce accidental matches.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Embedding model mismatch 🐞 Bug ≡ Correctness
Description
knowledge:searchWithEmbeddings always embeds the query with text-embedding-3-small, which can
diverge from the workspace’s configured/legacy embedding model and produce incorrect vector search
results for those workspaces.
Code

packages/convex/convex/knowledge.ts[R258-282]

+const DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
+const KNOWLEDGE_SEARCH_DEFAULT_LIMIT = 20;
+const KNOWLEDGE_SEARCH_MAX_LIMIT = 50;
+
+export const searchWithEmbeddings = authAction({
+  args: {
+    workspaceId: v.id("workspaces"),
+    query: v.string(),
+    contentTypes: v.optional(v.array(contentTypeValidator)),
+    limit: v.optional(v.number()),
+  },
+  permission: "articles.read",
+  handler: async (ctx, args): Promise<KnowledgeSearchResult[]> => {
+    const limit = Math.max(
+      1,
+      Math.min(args.limit ?? KNOWLEDGE_SEARCH_DEFAULT_LIMIT, KNOWLEDGE_SEARCH_MAX_LIMIT)
+    );
+
+    const aiClient = createAIClient();
+    const runQuery = getShallowRunQuery(ctx);
+
+    const { embedding } = await embed({
+      model: aiClient.embedding(DEFAULT_EMBEDDING_MODEL),
+      value: args.query,
+    });
Evidence
The new action hard-codes DEFAULT_EMBEDDING_MODEL when generating the query embedding, while the
codebase explicitly supports resolving a workspace’s embedding model (including a legacy model) and
uses it in other embedding-based search paths; this makes searchWithEmbeddings inconsistent with
the rest of the system when settings.embeddingModel is not the default.

packages/convex/convex/knowledge.ts[258-282]
packages/convex/convex/lib/embeddingModels.ts[2-36]
packages/convex/convex/suggestions.ts[348-378]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`packages/convex/convex/knowledge.ts` implements `searchWithEmbeddings`, but it always embeds the query with a hard-coded model (`text-embedding-3-small`). The rest of the system supports selecting/resolving a workspace embedding model (including legacy), so this creates incorrect/irrelevant similarity results whenever the workspace isn’t using the default model.

### Issue Context
- `resolveContentEmbeddingModel()` allows legacy models.
- Other vector search code paths resolve and use the workspace’s embedding model.

### Fix Focus Areas
- packages/convex/convex/knowledge.ts[258-282]

### Implementation notes
- Option A (recommended): read the workspace’s AI settings inside `searchWithEmbeddings` and use `resolveContentEmbeddingModel(settings.embeddingModel)` for the query embedding.
- Option B: add an optional `embeddingModel` argument and resolve it via `resolveContentEmbeddingModel()`.
- Ensure the chosen model matches the model used when generating/storing `contentEmbeddings` for that workspace.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@djanogly djanogly merged commit 4a20fec into main Apr 16, 2026
4 of 5 checks passed
Comment thread CLAUDE.md

When working on Convex code, **always read `convex/_generated/ai/guidelines.md` first** for important guidelines on how to correctly use Convex APIs and patterns. The file contains rules that override what you may have learned about Convex from training data.

Convex agent skills for common tasks can be installed by running `npx convex ai-files install`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. claude.md uses npx 📘 Rule violation § Compliance

The new CLAUDE.md instructs running npx convex ai-files install, which violates the requirement
to use pnpm for package management/CLI execution. This introduces non-standard tooling guidance
for the repo.
Agent Prompt
## Issue description
`CLAUDE.md` includes a `npx` command (`npx convex ai-files install`), which violates the repo’s PNPM-only rule.

## Issue Context
Docs are included in the compliance scan; guidance must not recommend `npx`/`npm`/`yarn` when `pnpm` alternatives exist.

## Fix Focus Areas
- CLAUDE.md[1-7]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 128 to +135
const GET_AI_SETTINGS_REF: SuggestionQueryRef<
{ workspaceId: Id<"workspaces"> },
Doc<"aiAgentSettings"> | null
> = makeFunctionReference<"query", { workspaceId: Id<"workspaces"> }, Doc<"aiAgentSettings"> | null>(
"suggestions:getAiSettings"
);
> = makeFunctionReference<
"query",
{ workspaceId: Id<"workspaces"> },
Doc<"aiAgentSettings"> | null
>("suggestions:getAiSettings");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. get_ai_settings_ref string ref 📘 Rule violation ⌂ Architecture

GET_AI_SETTINGS_REF is created via makeFunctionReference("suggestions:getAiSettings") even
though generated internal refs are available. This violates the required ordering for Convex
backend function references and bypasses codegen-based correctness guarantees.
Agent Prompt
## Issue description
`suggestions.ts` defines `GET_AI_SETTINGS_REF` using `makeFunctionReference("suggestions:getAiSettings")` even though a generated `internal` ref should be used.

## Issue Context
The backend reference ordering requires using generated refs first to avoid string drift and to keep references aligned with Convex codegen.

## Fix Focus Areas
- packages/convex/convex/suggestions.ts[128-135]
- packages/convex/convex/_generated/api.d.ts[392-403]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +284 to +299
const vectorResults = await ctx.vectorSearch("contentEmbeddings", "by_embedding", {
vector: embedding,
limit: limit * 8,
filter: (q) => q.eq("workspaceId", args.workspaceId),
});

const contentTypeSet =
args.contentTypes && args.contentTypes.length > 0 ? new Set(args.contentTypes) : null;

const embeddingDocs = await Promise.all(
vectorResults.map((result) =>
runQuery(internal.suggestions.getEmbeddingById, { id: result._id }).then((doc) =>
doc ? { ...doc, _score: result._score } : null
)
)
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Vector search query fan-out 🐞 Bug ➹ Performance

knowledge:searchWithEmbeddings performs limit * 8 vector search and then does Promise.all
runQuery calls per match; at the UI default (limit=20) this can trigger ~160 internal queries per
search and risks slowdowns/timeouts.
Agent Prompt
### Issue description
`knowledge:searchWithEmbeddings` does a vectorSearch with `limit * 8` and then performs one internal `runQuery` per vector result to fetch the embedding doc. With the inbox default limit (20), this becomes ~160 internal calls per search, which is likely to cause slow actions and/or timeouts.

### Issue Context
The fan-out happens even though only `limit` deduped results are ultimately returned.

### Fix Focus Areas
- packages/convex/convex/knowledge.ts[284-338]
- apps/web/src/app/inbox/hooks/useInboxConvex.ts[181-207]

### Implementation notes
- Reduce the `limit * 8` multiplier (or make it adaptive) to minimize worst-case work.
- Introduce a single internal query like `internal.suggestions.getEmbeddingsByIds({ ids: Id<"contentEmbeddings">[] })` to fetch embedding docs in batch.
- Consider an internal query that directly returns the minimal fields needed (contentType/contentId/title/snippet/updatedAt) for a list of embedding ids to avoid repeated round-trips.
- If batching isn’t feasible, at least cap concurrency and/or stop fetching once enough deduped results are found.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +74 to +90
const handleMessageClick = (event: React.MouseEvent<HTMLDivElement>) => {
const target = event.target;
if (!target) {
return;
}
const element = target instanceof Element ? target : (target as Text).parentElement;
if (!element) {
return;
}
const articleLink = element.closest("[data-article-id]");
if (articleLink) {
event.preventDefault();
event.stopPropagation();
const articleId = articleLink.getAttribute("data-article-id");
if (articleId) {
onSelectArticle(articleId as Id<"articles">);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Unvalidated article-id click 🐞 Bug ☼ Reliability

The widget treats any clicked element with [data-article-id] as an article link and casts the
attribute value to Id<"articles"> without validation; because shared markdown allows raw HTML and
now allows data-article-id, crafted message content can trigger Convex v.id("articles") argument
validation errors at runtime.
Agent Prompt
### Issue description
The widget click handler opens an article for any element matching `[data-article-id]` and casts the attribute to `Id<"articles">` without runtime validation. Because shared markdown supports raw HTML and now allows `data-article-id` through sanitization, a crafted message can inject an invalid `data-article-id` and cause Convex `v.id("articles")` argument validation errors when the widget tries to fetch the article.

### Issue Context
- `@opencom/web-shared` markdown uses `MarkdownIt({ html: true })`.
- DOMPurify allows `data-article-id`.
- The click handler matches `[data-article-id]` regardless of whether the element is a validated `article:` link.

### Fix Focus Areas
- packages/web-shared/src/markdown.ts[4-35]
- packages/web-shared/src/markdown.ts[92-139]
- apps/widget/src/components/conversationView/MessageList.tsx[74-91]

### Implementation notes
- In `enforceSafeLinksAndMedia`, proactively remove `data-article-id` from all elements/anchors by default, and only set it when the href is a validated `article:<id>` link.
- In the widget click handler, validate `articleId` before calling `onSelectArticle` (e.g., ensure it matches the same strict format you generate/accept for article ids) and ignore clicks when invalid.
- Optionally scope the selector to anchors only (e.g., `closest('a[data-article-id]')`) to reduce accidental matches.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

1 participant