Skip to content

feat(wren-ui): add reasoning api#1388

Merged
wwwy3y3 merged 16 commits intomainfrom
feature/reasoning-api
Mar 18, 2025
Merged

feat(wren-ui): add reasoning api#1388
wwwy3y3 merged 16 commits intomainfrom
feature/reasoning-api

Conversation

@wwwy3y3
Copy link
Copy Markdown
Member

@wwwy3y3 wwwy3y3 commented Mar 11, 2025

Description

  1. Update asking-related query / mutations to be able to provide a taskId, then asking tasks will be tracked at background.
  2. The progress of task could be access from askingTask query or from the field askingTask of thread/thread response

How to use new API

Create thread with taskId

mutation CreateThread($data: CreateThreadInput!) {
  createThread(data: $data) {
    id
    summary
  }
}

-- payload
{
  "data": {
    "question": "Which are the top 3 cities with the highest number of orders",
    "taskId": "c2d07e74-6d7c-4ed1-9fca-28f134e3aa80"
  }
}

CreateThreadResponse mutation has the same taskId parameter.

Get asking task from thread response

query ThreadResponse($responseId: Int!) {
  threadResponse(responseId: $responseId) {
    id
    threadId
    question
    sql
    askingTask {
      status
      type
      error {
        code
        shortMessage
        message
        stacktrace
      }
      candidates {
        type
        sql
        view {
          id
          name
          statement
          displayName
        }
      }
      rephrasedQuestion
      intentReasoning
      sqlGenerationReasoning
      retrievedTables
      invalidSql
      traceId
    }
  }
}
  • SQL field will be null until background tracker successfully get SQL from ai service & record it in db.

Use recommended question

mutation CreateThreadResponse($threadId: Int!, $data: CreateThreadResponseInput!) {
  createThreadResponse(threadId: $threadId, data: $data) {
    id
    threadId
    question
    sql
    ...
  }
}

-- payload
{
  "threadId": 19,
  "data": {
    "question": "Which are the top 3 cities with the highest number of orders",
    "sql": "SELECT\n  \"c\".\"customer_city\" AS \"city\",\n  COUNT(\"o\".\"order_id\") AS \"order_count\"\nFROM\n  \"olist_orders_dataset\" AS \"o\"\n  JOIN \"olist_customers_dataset\" AS \"c\" ON \"o\".\"customer_id\" = \"c\".\"customer_id\"\nGROUP BY\n  \"c\".\"customer_city\"\nORDER BY\n  \"order_count\" DESC\nLIMIT\n  3"
  }
}

Just provide question and sql.

Rerun asking task

mutation RerunAskingTask($responseId: Int!) {
  rerunAskingTask(responseId: $responseId)
}

-- payload
{
  "responseId": 36
}

Summary by CodeRabbit

  • New Features

    • Enhanced ask operations now return additional details such as rephrased questions, SQL generation reasoning, retrieved tables, and trace identifiers.
    • Introduced a new task tracking system allowing for the creation, retrieval, and cancellation of asking tasks.
    • Added a new database table for managing asking tasks and modified existing tables to accommodate new relationships.
    • Added a new mutation to rerun asking tasks based on response IDs.
    • New error codes introduced to enhance user feedback for general and misleading queries.
  • Refactor

    • Streamlined thread and response creation by removing unnecessary view-related inputs.
    • Improved response updates by conditionally sourcing SQL information when available.
  • Chores

    • Implemented database schema updates to support new task tracking capabilities and ensure consistency across data relationships.
    • Expanded telemetry events to track new actions related to asking tasks.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 11, 2025

Walkthrough

This pull request introduces a new database table (asking_task) and a migration to add a foreign key column (asking_task_id) to the thread_response table. It updates the transformation logic and type definitions for ask results by adding extra properties. A new repository for managing asking tasks has been added, and adjustments were made to resolvers and the GraphQL schema by removing the viewId property. The asking task tracker now integrates a view repository to conditionally update SQL based on the presence of a view ID, with corresponding service export and instantiation updates.

Changes

File(s) Change Summary
wren-ui/migrations/20250509...create_asking_task.js
wren-ui/migrations/20250509...add_task_id_to_thread.js
New migration files: create the asking_task table with necessary columns and foreign keys; add a nullable asking_task_id column (with proper constraints) to the thread_response table.
wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts
wren-ui/src/apollo/server/models/adaptor.ts
Updated the transformAskResult method to include new properties in the returned object; extended the AskResult type with additional optional properties.
wren-ui/src/apollo/server/repositories/askingTaskRepository.ts
wren-ui/src/apollo/server/repositories/threadResponseRepository.ts
wren-ui/src/apollo/server/repositories/index.ts
Introduced a new repository for managing asking tasks, including data transformation methods and error handling; updated the thread response repository to include an optional askingTaskId field and modified the sql property; re-exported the new repository.
wren-ui/src/apollo/server/resolvers/askingResolver.ts
wren-ui/src/apollo/server/schema.ts
Modified resolver methods and GraphQL input types: removed the viewId property from thread creation inputs and adjusted handling of the sql property.
wren-ui/src/apollo/server/services/askingService.ts
wren-ui/src/apollo/server/services/askingTaskTracker.ts
wren-ui/src/apollo/server/services/index.ts
wren-ui/src/common.ts
Removed view-related logic from the asking service; added a new dependency on IViewRepository in AskingTaskTracker to conditionally update thread responses with SQL from views; updated service exports and the instantiation of the task tracker.

Possibly related PRs

  • feat: Implement sql-pair API #1372: The changes in the main PR, which involve creating a new database table for asking_task, are related to the retrieved PR as both involve database schema modifications and the introduction of new functionalities that reference the same underlying data structures, specifically through foreign key relationships.
  • chore(wren-ai-service): improve text2sql #1208: The changes in the main PR, which involve creating a new database table asking_task and its associated foreign key references, are related to the retrieved PR, as it introduces a nullable integer column asking_task_id in the thread_response table that references the asking_task table. This establishes a direct connection between the two PRs at the database schema level.
  • feat(wren-ui): use intent reasoning instead of hard code string for misleading query #1217: The changes in the main PR, which introduce a new database migration for the asking_task table, are related to the retrieved PR as both involve modifications to the AskingTask type, specifically adding properties that enhance the structure and functionality of the task management system.

Suggested labels

module/ui, module/ai-service

Poem

I'm just a rabbit hopping in code,
Discovering migrations along a winding road.
New tasks are blooming in our DB soil,
With SQL and queries, making data toil.
I cheer the changes with a skip and a grin,
Carrots and code—let the adventures begin!
🥕🐇

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@wwwy3y3 wwwy3y3 force-pushed the feature/reasoning-api branch from bbc474d to 864e082 Compare March 11, 2025 20:18
@wwwy3y3
Copy link
Copy Markdown
Member Author

wwwy3y3 commented Mar 11, 2025

@coderabbitai summary

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 11, 2025

✅ Actions performed

Summary regeneration triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (2)
wren-ui/src/apollo/server/services/askingService.ts (1)

540-545: 🛠️ Refactor suggestion

Missing explicit error handling for createAskingTask.

When askingTaskTracker.createAskingTask fails (e.g., DB errors, service unavailability), the code does not catch or handle the exception. Consider adding a try/catch block or error wrapper to provide better error messages and rollback logic as needed.

    try {
      const response = await this.askingTaskTracker.createAskingTask({
        query: input.question,
        history,
        deployId,
      });
    } catch (err) {
      // handle error more gracefully
      throw err;
    }
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

361-374: ⚠️ Potential issue

Remove duplicated isResultChanged method.

Lines 363-373 repeat the logic from lines 346-359. This appears to be a merge artifact.

361 }
362
-  private isResultChanged(
-    previousResult: AskResult,
-    newResult: AskResult,
-  ): boolean {
-    if (previousResult?.status !== newResult.status) {
-      return true;
-    }
-    return false;
-  }
374 }
🧹 Nitpick comments (9)
wren-ui/src/apollo/server/schema.ts (2)

587-592: Add caution for potential PII & handle optional fields robustly.

These new fields (rephrasedQuestion, sqlGenerationReasoning, retrievedTables, invalidSql, traceId) help provide context for the asking tasks. However, ensure none of them inadvertently carries user-sensitive data or personally identifiable information. Consider auditing or sanitizing data before storing. Also, confirm each field’s optional nature is acceptable (e.g., verifying that analytics, logs, or other services gracefully handle null/undefined values).


710-710: Ensure null-handling logic for the askingTask field.

askingTask is introduced as a nullable field. Make sure clients understand that the task may not always be available or that the request for an asking task might fail. Properly handle these scenarios in the UI or API consumers to avoid runtime errors.

wren-ui/src/apollo/server/services/askingService.ts (2)

65-65: Add clarifying documentation for trackedAskingResult.

The optional property trackedAskingResult is convenient for passing the results of an ongoing asking task. Consider adding inline comments or JSDoc to explain how it’s intended to be set, read, and updated. This will help maintain clarity for contributors.


599-605: Consider fallback or error logging in task binding block.

When binding the thread response via askingTaskTracker.bindThreadResponse, ensure that missing or invalid IDs don’t cause hidden failures. For instance, if input.trackedAskingResult.queryId is undefined, the method may fail silently or produce an unclear error. Logging fallback logic or verifying input might help.

wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (2)

1-26: Add an index or unique constraint for queryId if queries are frequent.

This new repository and model definition look solid. Consider indexing queryId in the asking_task table to speed up frequent lookups and sustain performance. Also verify that concurrency or unique constraints align with how queryId is generated.


27-71: Ensure robust validation in transformFromDBData and transformToDBData.

Converting JSON and handling snake_case/camelCase is done correctly. Be mindful of scenarios where detail might be large or have unexpected structure. Properly handle JSON parse failures, e.g., wrap JSON.parse with try/catch or provide fallback logic to guard against malformed data.

wren-ui/src/apollo/server/services/askingTaskTracker.ts (3)

15-16: Consider making the debug logging level configurable.

By hardcoding logger.level = 'debug', production environments may generate excessive logs. Allowing a configurable logging level via environment variables could improve maintainability.


110-115: Use optional chaining for cleaner checks.

Instead of performing if (trackedTask && trackedTask.result) { ... }, you can use optional chaining to simplify your logic.

- if (trackedTask && trackedTask.result) {
+ if (trackedTask?.result) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


168-285: Consider a more robust concurrency approach in pollTasks.

This method uses a set to track running jobs and concurrently processes tasks with Promise.allSettled. For more complex scenarios, you might want to implement prioritized queues or bounded concurrency to avoid potential resource contention or partial results when scaling.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d11477a and 864e082.

📒 Files selected for processing (18)
  • wren-ui/migrations/20250509000000_create_asking_task.js (1 hunks)
  • wren-ui/migrations/20250509000001_add_task_id_to_thread.js (1 hunks)
  • wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts (1 hunks)
  • wren-ui/src/apollo/server/models/adaptor.ts (1 hunks)
  • wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (1 hunks)
  • wren-ui/src/apollo/server/repositories/index.ts (1 hunks)
  • wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (3 hunks)
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts (12 hunks)
  • wren-ui/src/apollo/server/schema.ts (4 hunks)
  • wren-ui/src/apollo/server/services/askingService.ts (15 hunks)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
  • wren-ui/src/apollo/server/services/index.ts (1 hunks)
  • wren-ui/src/common.ts (7 hunks)
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts (2 hunks)
  • wren-ui/src/apollo/server/schema.ts (0 hunks)
  • wren-ui/src/apollo/server/services/askingService.ts (2 hunks)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (4 hunks)
  • wren-ui/src/common.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (29)
wren-ui/migrations/20250509000001_add_task_id_to_thread.js (1)

1-25: Migration looks well-structured

This migration properly adds the asking_task_id foreign key to the thread_response table with appropriate nullability and cascade behavior. The down migration also correctly handles the cleanup order by dropping the foreign key first.

The migration filename contains the date "20250509", which appears to be in the future (2025). Please verify if this is intentional for migration sequencing or if it should be adjusted to the current year.

wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts (1)

517-528: The transformation logic looks well-structured.

The addition of new properties to the AskResult object enhances the response with more detailed information from the AI service. The snake_case to camelCase conversion is applied consistently, and all new fields are properly extracted from the response body.

wren-ui/migrations/20250509000000_create_asking_task.js (2)

5-26: Well-structured database table creation for the new asking task tracking feature.

The table structure is comprehensive with appropriate constraints:

  • Primary key and auto-incrementing ID
  • Unique constraint on query_id to ensure no duplicate tasks
  • Proper foreign key relationships with cascade deletion to maintain referential integrity
  • JSON column for flexible detail storage
  • Timestamps for tracking creation and updates

32-34: Migration rollback looks good.

The down function properly drops the table when the migration needs to be rolled back.

wren-ui/src/common.ts (6)

17-17: Integration of the new AskingTaskRepository.

The import is properly added to the existing list of repositories.


32-32: Integration of the new AskingTaskTracker service.

The import is properly added to the existing list of services.


65-65: Repository instantiation looks good.

The askingTaskRepository is instantiated with the existing knex instance, following the pattern used for other repositories.


108-112: Proper service initialization with dependencies.

The AskingTaskTracker is instantiated with the correct dependencies:

  • wrenAIAdaptor for interacting with the AI service
  • askingTaskRepository for persistent storage of asking tasks
  • threadResponseRepository for relating tasks to thread responses

This follows the dependency injection pattern used throughout the application.


123-123: Integration with existing AskingService.

The askingTaskTracker is properly injected into the askingService, allowing it to leverage the new task tracking functionality.


163-163: Proper export of new components.

Both the repository and tracker are exported in the return object, making them accessible to the rest of the application.

Also applies to: 178-178

wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (3)

44-44: Good addition of the foreign key relationship.

The optional askingTaskId property establishes the relationship with the new asking_task table, supporting the feature of tracking asking tasks in the background.


48-48: Making SQL field optional is appropriate.

Changing the sql property from required to optional is a good decision as there may be cases where a thread response exists without a corresponding SQL query.


114-139: Update method properly handles optional fields.

The updateOne method has been enhanced to:

  1. Accept optional sql and viewId parameters
  2. Handle these fields properly in the transformation logic, setting them to undefined when not provided

This aligns well with the changes to the ThreadResponse interface and ensures proper handling of optional fields.

wren-ui/src/apollo/server/schema.ts (4)

623-623: Validate usage of the new taskId field in CreateThreadInput.

Allowing an external taskId to be passed in is useful for referencing background tasks. Ensure front-end and other clients provide consistent or valid IDs (e.g., existence in the system, correct format), and handle any conflicts if taskId is invalid or previously associated with another thread.


630-630: Consider verifying the new taskId in CreateThreadResponseInput.

Similar to CreateThreadInput, taskId is introduced here. Double-check that incoming requests successfully correlate a valid task to the newly created thread response. Discrepancies in taskId could lead to orphaned or incorrectly bound tasks.


705-705: Beware of potential backward incompatibility by changing sql from non-nullable to nullable.

Changing sql: String! to sql: String can break clients expecting a non-null string. Confirm that downstream usage and client-side code handle the possibility of null or missing SQL string without error, especially if older consumers rely on the field’s prior non-null guarantee.


889-889: Confirm handling of nullable return value in askingTask query.

The schema’s askingTask(taskId: String!): AskingTask can return AskingTask | null; confirm that consumers properly handle null. Any mismatch could cause confusion or unhandled errors if a non-existent or invalid taskId is requested.

wren-ui/src/apollo/server/services/askingService.ts (4)

39-39: Review import usage for IAskingTaskTracker and TrackedAskingResult.

This new import correctly references the IAskingTaskTracker interface and the TrackedAskingResult type. Ensure the source file (./askingTaskTracker) is properly maintained and tested, so that changes to the tracker keep the service stable.


108-109: Validate “getAskingTask” and “getAskingTaskById” usage.

The newly introduced methods offer direct retrieval of a tracked task result by either taskId or numeric ID. Verify that both methods handle nonexistent or stale tasks gracefully, and confirm no uncaught exceptions occur if the task is already deleted or nonexistent.


367-380: Confirm the lifecycle and injection of askingTaskTracker.

The new askingTaskTracker field and constructor parameter look correct for dependency injection. Ensure that test environments and mocking scenarios properly instantiate this service, and no memory leaks or mis-scoped references occur during server shutdown.


555-555: Check cancellation edge cases for cancelAskingTask.

this.askingTaskTracker.cancelAskingTask(taskId) may fail if the task is already canceled or never existed, potentially throwing an error. Confirm that these scenarios are properly caught and that the rest of the application can handle an “already canceled” or “not found” outcome without confusion.

wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

63-82: Recheck the polling startup sequence for concurrency or timing issues.

Calling this.startPolling() directly within the constructor might introduce edge cases if other services are not fully initialized or if concurrency is a concern. Confirm that no race conditions arise from early polling.

wren-ui/src/apollo/server/resolvers/askingResolver.ts (4)

49-54: Enhanced extensibility acknowledged.

These additional optional properties (e.g., rephrasedQuestion, sqlGenerationReasoning, etc.) allow for richer context in resultant tasks. This is a clean way to accommodate new data.


195-197: Verify null-return impact on downstream logic.

Returning null if askResult is missing may cause consumer code to fail if it expects a valid object. Ensure that clients or calling logic handle this case gracefully.


232-255: Clean handling of threadInput based on taskId.

The logic to retrieve an existing asking task or fallback to direct input is well-structured. This approach avoids duplication and clarifies the data flow for thread creation.


609-639: Transformation logic is well-factored.

The transformAskingTask method cleanly separates data extraction from the subsequent resolver logic, improving readability. Great job structuring the final AskingTask object.

wren-ui/src/apollo/server/repositories/index.ts (1)

17-17: Exports added correctly

The new export for askingTaskRepository follows the established pattern in this file for making repository functionality available throughout the application. This is a clean addition that will enable tracking of asking tasks as described in the PR objectives.

wren-ui/src/apollo/server/services/index.ts (1)

9-9: Exports properly structured

The export of the new askingTaskTracker service follows the consistent pattern used in this file. This export makes the asking task tracking service available for dependency injection and use by other components, supporting the PR objective of enabling background tracking of asking tasks.

wren-ui/src/apollo/server/models/adaptor.ts (1)

124-130: Good type extension with backward compatibility

The addition of optional properties to the AskResult type enhances the reasoning API functionality while maintaining backward compatibility. These new fields provide valuable context about the asking process:

  • rephrasedQuestion - captures how the system understood the user's question
  • sqlGenerationReasoning - explains SQL generation logic (pairs well with existing intentReasoning)
  • retrievedTables - shows which tables were considered relevant to the query
  • invalidSql - stores any invalid SQL that was generated
  • traceId - enables tracing for debugging and monitoring

All properties are correctly marked as optional with the ? modifier, ensuring existing code won't break.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

111-126: getAskingResult method
Consider optional chaining to simplify the trackedTask && trackedTask.result checks.

- if (trackedTask && trackedTask.result) {
+ if (trackedTask?.result) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

wren-ui/src/apollo/server/resolvers/askingResolver.ts (1)

609-641: transformAskingTask method
Collecting candidates and retrieving views on-the-fly is convenient. If the number of candidates grows, consider caching.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 864e082 and 3f99918.

📒 Files selected for processing (3)
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts (11 hunks)
  • wren-ui/src/apollo/server/schema.ts (4 hunks)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (28)
wren-ui/src/apollo/server/schema.ts (5)

587-593: New fields in the AskingTask type look good.
These additional properties enhance the information available for each asking task, providing richer debugging and result tracking.


623-623: taskId addition to CreateThreadInput is consistent.
Adding taskId aligns with the new approach of referencing existing asking tasks.


629-629: taskId addition to CreateThreadResponseInput is similarly aligned.
This supports the same design pattern for referencing existing asking tasks in thread responses.


709-709: askingTask field in ThreadResponse.
This addition properly associates each response with an asking task if present.


888-888: askingTask(taskId: String!) now returns AskingTask (nullable).
This change aligns with the resolver’s ability to return null if the task is not found.

wren-ui/src/apollo/server/services/askingTaskTracker.ts (15)

1-18: Imports and logger setup appear correct.
The logger’s debug level ensures detailed polling logs.


19-34: TrackedTask and TrackedAskingResult interfaces
They are well-defined for typed result tracking.


35-51: IAskingTaskTracker interface
The contract is clearly outlined, matching the tracker’s responsibilities.


53-87: Class fields and constructor
The constructor neatly injects all necessary dependencies and starts polling automatically.


89-109: createAskingTask method
Error handling and logging are robust. Task creation logic looks straightforward.


128-135: getAskingResultById method
Neatly reuses getAskingResult by reference to queryId.


137-139: cancelAskingTask method
Delegated cancellation logic is concise and clear.


141-146: stopPolling method
Stops the polling interval cleanly.


147-165: bindThreadResponse method
Associating the in-memory tracked task with a DB record is straightforward.


166-171: startPolling
Well-defined approach, scheduling periodic polls via setInterval.


172-303: pollTasks method
Runs concurrent checks with Promise.allSettled. The memory retention cleanup is also handled neatly.


305-330: getAskingResultFromDB
Fetching from the repository if not found in memory is a good fallback approach.


331-353: updateTaskInDatabase
Updates or creates records to persist changes. Logic is clear.


355-361: isTaskFinalized
Checks final states elegantly using a small array of statuses.


363-373: isResultChanged
Currently checks only the status. For deeper comparisons, consider further logic if needed.

wren-ui/src/apollo/server/resolvers/askingResolver.ts (8)

19-19: Importing AskingDetailTaskInput.
No issues.


29-29: Importing TrackedAskingResult.
Ensures typed usage in transformation.


108-108: Binding this.transformAskingTask.
Maintaining the correct this context is appropriate here.


196-198: Returning null if askResult is falsy.
This aligns with the updated schema allowing a nullable AskingTask.


230-230: taskId added to create thread input.
Allows referencing an existing task when creating a thread.


372-373: taskId added to createThreadResponse input.
Same concept extended to thread responses.


385-397: Checking taskId before using fallback data.
The error thrown if the task is missing is helpful for debugging.


573-581: Nested resolver for sql and askingTask.
Conditionally formatting SQL and fetching the mapped AskingTask aligns with the schema changes.

@wwwy3y3
Copy link
Copy Markdown
Member Author

wwwy3y3 commented Mar 12, 2025

Note: Change to pipeline_id from taskId in our codebase & API

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (6)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (6)

115-122: Use optional chaining for safer property access

Consider using optional chaining to make the code more concise and safer.

- if (trackedTask && trackedTask.result) {
+ if (trackedTask?.result) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


223-225: Fix typo in comment

There's a typo in the comment - "MISLEADING_QUER" should be "MISLEADING_QUERY".

- // if it's identified as GENERAL or MISLEADING_QUER
+ // if it's identified as GENERAL or MISLEADING_QUERY

369-379: Enhanced result change detection logic

The current implementation of isResultChanged only checks for status changes, but there could be other important changes like response content or SQL that might be worth detecting.

Consider expanding the result change detection to include more fields:

 private isResultChanged(
   previousResult: AskResult,
   newResult: AskResult,
 ): boolean {
   // check status change
   if (previousResult?.status !== newResult.status) {
     return true;
   }
+  
+  // check for changes in response content
+  const prevResponse = previousResult?.response?.[0];
+  const newResponse = newResult?.response?.[0];
+  
+  if (prevResponse?.sql !== newResponse?.sql) {
+    return true;
+  }
+  
+  // Compare other relevant fields
+  // For example, check if viewId has changed
+  if (prevResponse?.viewId !== newResponse?.viewId) {
+    return true;
+  }

   return false;
 }

239-240: Task ID tracking during database update

When updating an existing task, you should also update the task ID in memory (similar to what's done for new tasks on line 351).

 logger.info(`Updating task ${queryId} in database`);
 await this.updateTaskInDatabase(queryId, task);
+ // ensure the task ID is properly tracked in memory
+ if (this.trackedTasks.get(queryId) && !this.trackedTasks.get(queryId).taskId) {
+   const taskRecord = await this.askingTaskRepository.findByQueryId(queryId);
+   if (taskRecord) {
+     this.trackedTasks.get(queryId).taskId = taskRecord.id;
+   }
+ }

250-271: SQL update logic could be more DRY

The conditional logic for updating SQL based on whether there's a viewId or not could be refactored to be more DRY.

-                  if (response.viewId) {
-                    // get sql from the view
-                    const view = await this.viewRepository.findOneBy({
-                      id: response.viewId,
-                    });
-                    await this.threadResponseRepository.updateOne(
-                      task.threadResponseId,
-                      {
-                        sql: view.statement,
-                        viewId: response.viewId,
-                      },
-                    );
-                  } else {
-                    await this.threadResponseRepository.updateOne(
-                      task.threadResponseId,
-                      {
-                        sql: response?.sql,
-                      },
-                    );
-                  }
+                  const updateData: { sql?: string; viewId?: number } = {};
+                  
+                  if (response.viewId) {
+                    // get sql from the view
+                    const view = await this.viewRepository.findOneBy({
+                      id: response.viewId,
+                    });
+                    updateData.sql = view.statement;
+                    updateData.viewId = response.viewId;
+                  } else if (response?.sql) {
+                    updateData.sql = response.sql;
+                  }
+                  
+                  if (Object.keys(updateData).length > 0) {
+                    await this.threadResponseRepository.updateOne(
+                      task.threadResponseId,
+                      updateData
+                    );
+                  }

345-353: Add task tracking by ID after creation

When creating a new task, consider adding it to the trackedTasksById map as well, to ensure it's accessible via both query ID and task ID.

 const task = await this.askingTaskRepository.createOne({
   queryId,
   question: trackedTask.question,
   detail: trackedTask.result,
 });
 // update the task id in memory
 this.trackedTasks.get(queryId).taskId = task.id;
+ // track by task ID as well
+ this.trackedTasksById.set(task.id, this.trackedTasks.get(queryId));
 return;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f99918 and 7f5a5d1.

📒 Files selected for processing (1)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

21-21: Consider renaming taskId to pipeline_id

According to the PR comments, taskId should be changed to pipeline_id for better alignment with the project's standards.

Please verify if this change still needs to be implemented throughout the codebase.

@wwwy3y3 wwwy3y3 force-pushed the feature/reasoning-api branch from 7f5a5d1 to 6c73ee8 Compare March 17, 2025 16:54
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (2)

89-109: ⚠️ Potential issue

Method signature mismatch in createAskingTask implementation.

The implementation doesn't match the interface definition on lines 36-41. The interface defines additional parameters (question, threadId, threadResponseId) that are missing in the implementation.

Apply this diff to fix the method signature:

- public async createAskingTask(input: AskInput): Promise<{ queryId: string }> {
+ public async createAskingTask(
+   input: AskInput,
+   question?: string,
+   threadId?: number,
+   threadResponseId?: number,
+ ): Promise<{ queryId: string }> {

311-335: ⚠️ Potential issue

Inconsistent return type in getAskingResultFromDB.

The method returns null when no task record is found, but the return type is TrackedAskingResult without making it nullable.

Apply this diff to fix the return type:

- private async getAskingResultFromDB({
-   queryId,
-   taskId,
- }: {
-   queryId?: string;
-   taskId?: number;
- }): Promise<TrackedAskingResult> {
+ private async getAskingResultFromDB({
+   queryId,
+   taskId,
+ }: {
+   queryId?: string;
+   taskId?: number;
+ }): Promise<TrackedAskingResult | null> {
🧹 Nitpick comments (8)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (3)

115-122: Optional chaining opportunity in result handling.

The code should use optional chaining to safely access properties of potentially undefined objects.

Apply this diff to use optional chaining:

- if (trackedTask && trackedTask.result) {
+ if (trackedTask?.result) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


223-232: Typo in comment about AskResultType.

There's a typo in the comment: "MISLEADING_QUER" is missing the "Y".

Fix the typo in the comment:

- // if it's identified as GENERAL or MISLEADING_QUER
+ // if it's identified as GENERAL or MISLEADING_QUERY

172-309: Complex polling logic could benefit from more detailed comments.

The pollTasks method contains complex logic for tracking and updating task status. While the code is well-structured, additional comments explaining the decision points and state transitions would improve maintainability.

Consider adding more detailed comments to explain:

  1. The task lifecycle (creation, tracking, finalization)
  2. When and why tasks are removed from memory
  3. The criteria for database updates
  4. How thread response updates are triggered
wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (5)

41-56: Improve error handling and add type safety for transformFromDBData

The error message "Unexpected dbdata" is not descriptive enough. Consider also adding error handling for JSON.parse which could throw if malformed JSON is encountered.

  protected override transformFromDBData = (data: any) => {
    if (!isPlainObject(data)) {
-      throw new Error('Unexpected dbdata');
+      throw new Error('transformFromDBData: Expected plain object but received different type');
    }
    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));
    const transformData = mapValues(camelCaseData, (value, key) => {
      if (this.jsonbColumns.includes(key)) {
        if (typeof value === 'string') {
-          return value ? JSON.parse(value) : value;
+          if (!value) return value;
+          try {
+            return JSON.parse(value);
+          } catch (error) {
+            console.error(`Failed to parse JSON for ${key}:`, error);
+            return null;
+          }
        }
        return value;
      }
      return value;
    });
    return transformData as AskingTask;
  };

58-70: Improve error handling for transformToDBData

Similar to the previous comment, enhance the error message for better debugging and consider handling JSON.stringify errors.

  protected override transformToDBData = (data: any) => {
    if (!isPlainObject(data)) {
-      throw new Error('Unexpected dbdata');
+      throw new Error('transformToDBData: Expected plain object but received different type');
    }
    const transformedData = mapValues(data, (value, key) => {
      if (this.jsonbColumns.includes(key)) {
-        return JSON.stringify(value);
+        try {
+          return JSON.stringify(value);
+        } catch (error) {
+          console.error(`Failed to stringify JSON for ${key}:`, error);
+          return null;
+        }
      } else {
        return value;
      }
    });
    return mapKeys(transformedData, (_value, key) => snakeCase(key));
  };

1-11: Consider adding JSDoc documentation

The code would benefit from JSDoc comments for the interfaces and class to document their purpose, usage, and relationships with other components.

import { Knex } from 'knex';
import { BaseRepository, IBasicRepository } from './baseRepository';
import {
  camelCase,
  isPlainObject,
  mapKeys,
  mapValues,
  snakeCase,
} from 'lodash';
import { AskResult } from '../models/adaptor';

+/**
+ * Represents an asking task in the system, tracking the progress of questions
+ * and their responses through various stages of processing.
+ */
export interface AskingTask {

23-25: Add documentation for repository interface

Document the purpose of this repository interface to make it clear for other developers.

+/**
+ * Repository interface for managing AskingTask entities,
+ * providing methods to interact with the asking_task table.
+ */
export interface IAskingTaskRepository extends IBasicRepository<AskingTask> {
  findByQueryId(queryId: string): Promise<AskingTask | null>;
}

37-39: Consider adding unit tests for this repository

New repository classes should have appropriate unit tests to ensure data transformation and query methods work as expected.

Would you like me to suggest a test structure for this repository class?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f5a5d1 and 6c73ee8.

📒 Files selected for processing (13)
  • wren-ui/migrations/20250509000000_create_asking_task.js (1 hunks)
  • wren-ui/migrations/20250509000001_add_task_id_to_thread.js (1 hunks)
  • wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts (1 hunks)
  • wren-ui/src/apollo/server/models/adaptor.ts (1 hunks)
  • wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (1 hunks)
  • wren-ui/src/apollo/server/repositories/index.ts (1 hunks)
  • wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (3 hunks)
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts (11 hunks)
  • wren-ui/src/apollo/server/schema.ts (4 hunks)
  • wren-ui/src/apollo/server/services/askingService.ts (11 hunks)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
  • wren-ui/src/apollo/server/services/index.ts (1 hunks)
  • wren-ui/src/common.ts (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • wren-ui/src/apollo/server/repositories/index.ts
  • wren-ui/src/apollo/server/services/index.ts
  • wren-ui/migrations/20250509000001_add_task_id_to_thread.js
  • wren-ui/src/apollo/server/models/adaptor.ts
  • wren-ui/migrations/20250509000000_create_asking_task.js
  • wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts
  • wren-ui/src/apollo/server/repositories/threadResponseRepository.ts
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts
🧰 Additional context used
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 115-115: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (31)
wren-ui/src/common.ts (7)

18-18: Added AskingTaskRepository to the import statement.

Good addition. This repository is needed for the new asking task functionality.


33-33: Added AskingTaskTracker to the import statement.

Appropriate addition of the service that will handle the tracking of asking tasks.


68-68: Created an instance of AskingTaskRepository.

Good initialization of the repository following the established pattern in this file.


111-116: Added AskingTaskTracker initialization with proper dependencies.

The tracker is correctly initialized with all required dependencies: wrenAIAdaptor, askingTaskRepository, threadResponseRepository, and viewRepository. This follows the dependency injection pattern used throughout the codebase.


127-127: Added askingTaskTracker as a parameter to the AskingService.

Good integration with the existing service. This allows AskingService to leverage the new task tracking functionality.


171-172: Added askingTaskRepository to the exported components.

Properly exposed the repository for use by other components.


188-188: Added askingTaskTracker to the exported components.

Correctly exposed the tracker service so it can be accessed by other components in the application.

wren-ui/src/apollo/server/schema.ts (6)

587-593: Added detailed fields to AskingTask type to support reasoning pipeline.

These additional fields provide more detailed information about the asking task, including reasoning steps and intermediary results. This is a good enhancement that improves the explainability of the AI-generated results.


623-623: Replaced viewId with taskId in CreateThreadInput.

This change aligns with the PR objective to provide a taskId when making queries or mutations related to asking tasks. It allows for proper tracking of asking tasks in the background.


629-629: Replaced viewId with taskId in CreateThreadResponseInput.

Consistent with the change to CreateThreadInput, this maintains API coherence for task tracking.


704-704: Changed sql from non-nullable to nullable in ThreadResponse.

Making sql nullable allows for scenarios where the thread response might not have SQL yet, such as when an asking task is still in progress. However, ensure all client code properly handles null values.


709-709: Added askingTask field to ThreadResponse.

This is a valuable addition that allows clients to access the progress of a task through the thread response object, as mentioned in the PR objectives.


913-913: Updated askingTask query return type to be nullable.

The change from AskingTask! to AskingTask (making it nullable) allows this query to handle cases where the task might not exist. This is a good defensive programming practice.

wren-ui/src/apollo/server/services/askingService.ts (9)

38-38: Import IAskingTaskTracker and TrackedAskingResult.

Good addition of the necessary imports for the new task tracking system.


63-63: Replaced viewId with trackedAskingResult in AskingDetailTaskInput.

This change aligns with the PR objectives by moving from view-based references to task-based tracking. The TrackedAskingResult type provides more comprehensive information than just an ID.


106-107: Updated getAskingTask signature and added getAskingTaskById.

These method signatures now return TrackedAskingResult which provides more comprehensive information about an asking task. The addition of getAskingTaskById allows retrieving tasks by their database ID in addition to queryId.

Handle non-existent tasks gracefully in getAskingTask and getAskingTaskById.

While these methods delegate to this.askingTaskTracker, ensure the service or caller can handle scenarios where the result is null (e.g., the task record was purged, or the ID is invalid). Consider returning null or throwing a custom error that front-end clients can interpret.


365-365: Added askingTaskTracker as a private field and constructor parameter.

Good addition of the new tracker as a dependency, following the established dependency injection pattern in the service.

Also applies to: 377-377, 430-430


536-544: Updated createAskingTask to use the task tracker.

The implementation now delegates to the task tracker instead of directly calling the AI adaptor. This is a good approach that centralizes task management logic in the tracker class.


550-550: Updated cancelAskingTask to use the task tracker.

Similar to the createAskingTask change, this delegates task cancellation to the dedicated tracker.


558-564: Implemented getAskingTask and getAskingTaskById.

Both methods correctly delegate to the task tracker. Remember to handle null responses appropriately at the resolver level.


581-596: Updated thread creation logic to use task tracking.

The code now creates a thread response with an asking task ID and then binds the task to the thread response. This supports the new task tracking functionality while maintaining the existing thread creation flow.


637-652: Updated thread response creation to handle task tracking.

Similar to thread creation, this correctly binds the task to the thread response after creation.

wren-ui/src/apollo/server/services/askingTaskTracker.ts (7)

19-27: Well-defined TrackedTask interface.

Good definition of the interface for tracked tasks, including all necessary properties for status tracking and association with thread responses.


29-33: Created TrackedAskingResult type extending AskResult.

This type extension is a good approach, adding task-specific properties to the base AskResult.


35-51: Clear interface definition for IAskingTaskTracker.

The interface provides a well-defined contract for the task tracker with all necessary methods for creating, retrieving, canceling, and binding tasks.


53-87: Well-structured AskingTaskTracker class with flexible configuration.

The class has a good constructor with sensible defaults for polling intervals and memory retention. All dependencies are properly injected, and the class fields are well-organized.


147-164: Implement thread response binding with proper error handling.

Good implementation of the bindThreadResponse method, which includes error checking and updates both in-memory state and the database.


337-359: Efficient database update logic in updateTaskInDatabase.

The method only creates a new record if one doesn't exist, and otherwise updates the existing one. This prevents duplicate entries and maintains data integrity.


247-270: Conditional handling of view-based SQL.

The code properly handles both cases where a task result might include a viewId (getting SQL from the view) or direct SQL. This flexibility is important for supporting different types of task results.

wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (2)

12-21: AskingTask interface design looks good

The AskingTask interface is well-structured with appropriate optional properties and type definitions. The design allows for flexibility in task tracking with optional fields like question, threadId, and threadResponseId.


27-35:

Details

❓ Verification inconclusive

Consider PR objectives regarding taskId vs pipeline_id

Note that PR comments mentioned changing taskId to pipeline_id. Consider whether this interface and repository should reflect that naming convention.


🏁 Script executed:

#!/bin/bash
# Check if there are any references to pipeline_id in the codebase
# that might indicate the need for alignment with this repository

echo "Searching for pipeline_id references in the codebase:"
rg -p "pipeline_id" --type ts

echo "\nSearching for taskId references in the codebase:"
rg -p "taskId" --type ts

Length of output: 4427


Naming Convention Consistency (taskId vs. pipeline_id)
I checked the repository and found that all references—including GraphQL queries, resolvers, services, and client code—use taskId. There are no occurrences of pipeline_id anywhere in the codebase.

  • If the PR objectives intend to switch to pipeline_id globally, then this repository (and all related modules) should be updated accordingly.
  • If the intent is to remain consistent with the current usage, then keeping taskId is appropriate.

Please confirm the intended naming convention so that we can ensure consistency across the codebase.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

357-381: ⚠️ Potential issue

Type mismatch in getAskingResultFromDB return value.

The method returns null when no task record is found, but the return type is TrackedAskingResult without making it nullable.

Apply this diff to fix the return type:

- private async getAskingResultFromDB({
-   queryId,
-   taskId,
- }: {
-   queryId?: string;
-   taskId?: number;
- }): Promise<TrackedAskingResult> {
+ private async getAskingResultFromDB({
+   queryId,
+   taskId,
+ }: {
+   queryId?: string;
+   taskId?: number;
+ }): Promise<TrackedAskingResult | null> {
🧹 Nitpick comments (4)
wren-ui/src/apollo/server/utils/error.ts (3)

46-47: Fix typo in error code names

There's a spelling mistake in both error code names: "IDENTIED" should be "IDENTIFIED".

-  IDENTIED_AS_GENERAL = 'IDENTIED_AS_GENERAL',
-  IDENTIED_AS_MISLEADING_QUERY = 'IDENTIED_AS_MISLEADING_QUERY',
+  IDENTIFIED_AS_GENERAL = 'IDENTIFIED_AS_GENERAL',
+  IDENTIFIED_AS_MISLEADING_QUERY = 'IDENTIFIED_AS_MISLEADING_QUERY',

97-100: Update error message strings to match the fixed error codes

After fixing the typo in the error code names, remember to update the corresponding string keys.

-  [GeneralErrorCodes.IDENTIED_AS_GENERAL]:
-    'The question is identified as a general question, please follow-up ask with more specific questions.',
-  [GeneralErrorCodes.IDENTIED_AS_MISLEADING_QUERY]:
-    'The question is identified as a misleading query, please follow-up ask with more specific questions.',
+  [GeneralErrorCodes.IDENTIFIED_AS_GENERAL]:
+    'The question is identified as a general question, please follow-up ask with more specific questions.',
+  [GeneralErrorCodes.IDENTIFIED_AS_MISLEADING_QUERY]:
+    'The question is identified as a misleading query, please follow-up ask with more specific questions.',

123-125: Update short message strings to match the fixed error codes

These short message keys also need to be updated to match the fixed error codes.

-  [GeneralErrorCodes.IDENTIED_AS_GENERAL]: 'Identified as general question',
-  [GeneralErrorCodes.IDENTIED_AS_MISLEADING_QUERY]:
-    'Identified as misleading query',
+  [GeneralErrorCodes.IDENTIFIED_AS_GENERAL]: 'Identified as general question',
+  [GeneralErrorCodes.IDENTIFIED_AS_MISLEADING_QUERY]:
+    'Identified as misleading query',
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

421-431: Simplistic isResultChanged implementation.

The current isResultChanged method only checks for status changes, but more comprehensive change detection could improve performance by reducing unnecessary updates.

Consider extending the change detection to check other important fields:

private isResultChanged(
  previousResult: AskResult,
  newResult: AskResult,
): boolean {
  // Check if either result is null
  if (!previousResult || !newResult) {
    return previousResult !== newResult;
  }

  // check status change
  if (previousResult?.status !== newResult.status) {
    return true;
  }
  
+ // Check for changes in error
+ if (JSON.stringify(previousResult?.error) !== JSON.stringify(newResult?.error)) {
+   return true;
+ }
+
+ // Check for changes in response
+ if (JSON.stringify(previousResult?.response) !== JSON.stringify(newResult?.response)) {
+   return true;
+ }

  return false;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c73ee8 and 5cc08c6.

📒 Files selected for processing (7)
  • wren-ui/src/apollo/server/resolvers.ts (1 hunks)
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts (12 hunks)
  • wren-ui/src/apollo/server/schema.ts (5 hunks)
  • wren-ui/src/apollo/server/services/askingService.ts (11 hunks)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
  • wren-ui/src/apollo/server/telemetry/telemetry.ts (1 hunks)
  • wren-ui/src/apollo/server/utils/error.ts (3 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 136-136: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (31)
wren-ui/src/apollo/server/telemetry/telemetry.ts (1)

54-54: Added new telemetry event for rerunning asking tasks

This addition to the telemetry events aligns well with the new functionality for rerunning asking tasks that's being introduced in this PR.

wren-ui/src/apollo/server/resolvers.ts (1)

94-94: Added new mutation resolver for rerunning asking tasks

The implementation delegates to the AskingResolver as expected, following the established pattern in the codebase.

wren-ui/src/apollo/server/schema.ts (6)

587-593: Enhanced AskingTask type with additional context fields

These new fields will provide richer information about the asking task's execution, which will be helpful for debugging and providing better user feedback.


623-623: Replaced viewId with taskId in input types

Replacing viewId with taskId aligns with the PR objective of tracking asking tasks in the background. This change reflects a shift from view-based to task-based architecture.

Also applies to: 629-629


704-704: Made sql field nullable in ThreadResponse

Changing sql: String! to sql: String makes the field nullable. This has previously been commented on in a review, and it's important to ensure that all client code handles this change appropriately.

Ensure all UI components properly handle the nullable sql field in ThreadResponse. Client code that previously assumed sql was always present will need to add null checks to prevent runtime errors.

#!/bin/bash
# Find all places in the codebase where ThreadResponse.sql is accessed directly
rg -A 3 -B 3 "\.sql" --type=tsx --type=ts | grep -B 3 -A 3 "threadResponse" | grep -v "sql:"

709-709: Added askingTask field to ThreadResponse

This addition allows clients to access asking task details directly from thread responses, which simplifies the API by reducing the need for separate queries.


992-992: Added rerunAskingTask mutation

This new mutation implements the core functionality described in the PR objectives. It takes a response ID and returns a boolean indicating success.


913-913:

Details

❓ Verification inconclusive

Made askingTask query result nullable

Changing the return type from AskingTask! to AskingTask makes it nullable. Ensure that client code handles this potential null value appropriately.


🏁 Script executed:

#!/bin/bash
# Find all direct usages of the askingTask query to verify null handling
rg -A 5 "askingTask\(" --type=tsx --type=ts

Length of output: 73


Revised Verification Request: Verify Nullable Handling for askingTask Query

The initial search command failed due to an unrecognized file type ("tsx"). Please run the updated command below to search across both .ts and .tsx files and confirm that the client code handles the nullable response from the askingTask query appropriately:

After verifying the output, ensure that any affected client code is updated to manage the potential null value.


🏁 Script executed:

#!/bin/bash
rg -A 5 "askingTask\(" -g "*.{ts,tsx}"

Length of output: 1276


Nullable AskingTask Field: Verify Client-Side Null Handling
The update from AskingTask! to AskingTask in the schema now allows a null response. Our search shows that client code in wren-ui/src/apollo/client/graphql/home.ts (and its generated counterpart) invokes the askingTask query without any clear null-checks. Please verify that these areas either account for a potential null result (using conditional checks or optional chaining) or update them accordingly to avoid runtime issues.

wren-ui/src/apollo/server/services/askingService.ts (9)

38-38: Good addition of the new imports for task tracking.

The import of IAskingTaskTracker and TrackedAskingResult from './askingTaskTracker' supports the new functionality that tracks asking tasks in the background.


61-64: Replaced viewId with trackedAskingResult in AskingDetailTaskInput.

The replacement of viewId with trackedAskingResult aligns with the PR objectives of providing a taskId when making queries or mutations related to asking tasks. This change enables tracking of asking tasks in the background.


104-111: Interface updates to support the new task tracking functionality.

Good extension of the IAskingService interface with:

  1. A new rerunAskingTask method for rerunning tasks
  2. Updated getAskingTask return type to TrackedAskingResult
  3. Added getAskingTaskById method to retrieve tasks by ID

These changes properly define the contract for the implementation.


369-369: Properly initialized askingTaskTracker service in constructor.

The AskingService now correctly accepts and initializes the askingTaskTracker dependency, which enables the background tracking of asking tasks.

Also applies to: 381-392, 434-434


529-553: Updated createAskingTask to use askingTaskTracker.

The method now delegates to the askingTaskTracker service and includes support for rerunning cancelled tasks with new optional parameters. The code correctly handles the necessary deployment ID and history retrieval before delegating to the tracker.


555-584: Well-implemented rerunAskingTask method.

This new method allows rerunning an asking task from a previous thread response. It:

  1. Retrieves the original thread response
  2. Gets the original question
  3. Correctly sets up the input and payload
  4. Calls createAskingTask with the rerunFromCancelled flag

The implementation properly handles error cases and maintains thread relationships.


597-604: Handle non-existent tasks gracefully in getAskingTaskById.

Both getAskingTask and getAskingTaskById methods delegate to the tracker without any additional error handling, but should handle cases where tasks don't exist or have been purged.


612-639: Updated createThread to support task tracking.

The method has been updated to store the taskId from the tracked asking result and bind the thread response to the task. This enables tracking the relationship between threads and asking tasks.


664-694: Updated createThreadResponse to support task tracking.

Similar to the createThread method, this implementation has been updated to bind thread responses to asking tasks when a taskId is provided. The implementation properly handles the relationship between thread responses and asking tasks.

wren-ui/src/apollo/server/services/askingTaskTracker.ts (7)

20-54: Well-defined interfaces and types for the task tracker.

The interfaces and types (TrackedTask, TrackedAskingResult, CreateAskingTaskInput, and IAskingTaskTracker) provide a clear contract for the tracker implementation. The types properly extend existing types with the necessary tracking information.


55-89: Comprehensive class setup with proper dependency injection.

The AskingTaskTracker class is well-structured with:

  1. Clear property definitions
  2. Proper dependency injection in the constructor
  3. Default values for polling interval and memory retention time
  4. Initialization of the polling mechanism

This ensures that the tracker can be easily tested and configured.


91-130: Well-implemented createAskingTask method with error handling.

The method:

  1. Calls the AI service to create a task
  2. Validates input parameters
  3. Stores the task in memory
  4. Handles the special case for rerunning cancelled tasks
  5. Provides proper error handling and logging

The implementation is robust and correctly handles the various cases.


132-156: Effective implementation of getAskingResult methods.

Both getAskingResult and getAskingResultById methods check the in-memory cache first and fall back to the database if needed, providing an efficient implementation.

🧰 Tools
🪛 Biome (1.9.4)

[error] 136-136: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


168-185: Good implementation of bindThreadResponse.

The method properly updates both the in-memory tracking and the database record, maintaining consistency between the two.


193-355: Comprehensive polling mechanism with proper error handling.

The pollTasks method:

  1. Skips already running jobs
  2. Removes finalized tasks after the retention period
  3. Updates task status from the AI service
  4. Updates the database when needed
  5. Handles task finalization
  6. Updates thread responses
  7. Provides thorough error handling and logging

This implementation ensures that tasks are properly tracked and updated.


413-419: Good helper method for checking task finalization.

The isTaskFinalized method clearly defines when a task is considered finalized, making the code more maintainable and easier to understand.

wren-ui/src/apollo/server/resolvers/askingResolver.ts (7)

49-56: Enhanced AskingTask interface with additional properties.

The AskingTask interface has been extended with additional properties (rephrasedQuestion, sqlGenerationReasoning, retrievedTables, invalidSql, traceId, queryId) to provide more context about the task result. This makes the API more informative and enables better front-end experiences.


196-222: Updated getAskingTask with null handling and transformation.

The getAskingTask method now:

  1. Properly handles the null case when no task is found
  2. Uses the new transformAskingTask helper method to convert the result
  3. Maintains the existing telemetry logic

This ensures consistent error handling and data transformation.


227-258: Well-implemented createThread with task ID support.

The method has been updated to:

  1. Accept a taskId instead of a viewId
  2. Retrieve the asking task result when a taskId is provided
  3. Use the task's question and result for thread creation
  4. Fall back to the input data when no taskId is provided

This implementation properly supports the new task tracking functionality.


366-407: Similar good implementation in createThreadResponse.

Like createThread, this method has been updated to support taskId and retrieve asking task results. The implementation is consistent with the changes in createThread and properly handles the relationship between thread responses and asking tasks.


420-436: Well-implemented rerunAskingTask method.

This new method provides the ability to rerun an asking task from a previous thread response, which is a valuable feature for users. The implementation correctly:

  1. Retrieves the threadResponseId
  2. Calls the corresponding service method
  3. Sends the appropriate telemetry event
  4. Returns a boolean indicating success

The method is straightforward and focused.


593-600: Added askingTask resolver for thread responses.

This allows clients to access the associated asking task from a thread response, providing better visibility into the task's status and results. The implementation correctly handles null cases and transforms the result.


628-661: Comprehensive transformAskingTask helper method.

This method transforms the TrackedAskingResult into an AskingTask format expected by the GraphQL API. It:

  1. Constructs candidates from the response
  2. Resolves view information for each candidate
  3. Maps all the required fields including the new ones
  4. Handles the default type case

The implementation is thorough and properly handles all the necessary transformations.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (3)

18-18: Consider making logger level configurable.

Currently, the logger is explicitly set to debug mode. This might clutter logs in production. Consider making the logging level configurable so that different environments can set log levels appropriately.


136-136: Prefer optional chaining to simplify the condition.

This check can be simplified using optional chaining while preserving equivalent logic:

- if (trackedTask && trackedTask.result) {
+ if (trackedTask?.result) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 136-136: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


187-355: Review concurrency strategy for polling large numbers of tasks.

All tasks are polled in parallel every second, which can cause performance bottlenecks as the number of tasks grows. Consider implementing a concurrency limit or a more scalable batch strategy to avoid potential overload.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cc08c6 and 10f28f9.

📒 Files selected for processing (1)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 136-136: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (3)

22-22: Rename taskId to pipeline_id for consistency with the updated requirement.

Based on the PR objectives, the user indicated that taskId should be changed to pipeline_id for improved clarity. Please confirm the final naming requirement and update both variable names and references accordingly within the codebase.

Also applies to: 39-39, 100-100


253-274: Confirm error logic when task is identified as GENERAL or MISLEADING_QUERY.

Re-running a canceled task sets its status to FAILED if it falls under GENERAL or MISLEADING_QUERY. Please verify this aligns with your intended business logic, as it might override more granular error statuses or future re-run scenarios.


296-317: Verify multi-candidate handling logic.

Currently, only the first candidate is used to update the thread response. If multiple candidates or answers are expected, consider a loop or different selection policy to ensure all relevant results are processed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (6)
wren-ui/src/apollo/server/services/askingService.ts (6)

104-112: Parameter expansion for createAskingTask is coherent.
Introducing rerunFromCancelled, previousTaskId, and threadResponseId fosters clarity for re-running tasks. As the list of optional params grows, consider grouping them into a dedicated options object for cleaner maintainability.


566-597: Implementation of rerunAskingTask.

  1. Checks for an existing thread response.
  2. Reuses the original question.
  3. Calls createAskingTask with flags for re-running.

Potential improvements:

  • Add logic to handle partially finished tasks if needed.
  • Confirm any concurrency edge cases.

Otherwise, this is a clear approach to re-run.


621-623: Updated doc comments for creating a thread and AI task.
The stepwise breakdown is clearer. Consider revisiting them if future logic changes, but for now, they match the new workflow.


640-649: Binding the new thread response to an asking task if present.
This ensures full linkage. If taskId is invalid, consider optionally logging or gracefully ignoring. Right now, it assumes the tracker call always succeeds.


693-693: Applying the same askingTaskId assignment for new thread responses.
This duplicates logic from thread creation, but it’s consistent. If you foresee further expansion, factor out a helper.


696-705: Repeating the bind logic in createThreadResponse.
Identical logic to the previous segment. Consider extracting a helper to reduce duplication.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1905eb9 and 5e98711.

📒 Files selected for processing (3)
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts (13 hunks)
  • wren-ui/src/apollo/server/schema.ts (5 hunks)
  • wren-ui/src/apollo/server/services/askingService.ts (11 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • wren-ui/src/apollo/server/schema.ts
  • wren-ui/src/apollo/server/resolvers/askingResolver.ts
🧰 Additional context used
🧠 Learnings (1)
wren-ui/src/apollo/server/services/askingService.ts (2)
Learnt from: wwwy3y3
PR: Canner/WrenAI#1388
File: wren-ui/src/apollo/server/services/askingService.ts:599-604
Timestamp: 2025-03-17T19:26:10.835Z
Learning: Error handling for non-existent asking tasks in WrenAI is handled at the resolver level rather than in the service implementation.
Learnt from: wwwy3y3
PR: Canner/WrenAI#1388
File: wren-ui/src/apollo/server/services/askingService.ts:586-604
Timestamp: 2025-03-17T19:32:09.267Z
Learning: In WrenAI's askingService.ts, errors should be allowed to bubble up to the top-level error handler rather than being caught and logged at the method level.
🧬 Code Definitions (1)
wren-ui/src/apollo/server/services/askingService.ts (4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (2) (2)
  • TrackedAskingResult (31:35)
  • IAskingTaskTracker (42:53)
wren-ui/src/apollo/server/resolvers/askingResolver.ts (1) (1)
  • Task (38:40)
wren-ui/src/apollo/server/repositories/threadRepository.ts (1) (1)
  • Thread (17:27)
wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (1) (1)
  • ThreadResponse (42:52)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (18)
wren-ui/src/apollo/server/services/askingService.ts (18)

28-28: No issues with the additional import.
Looks like IViewRepository and Project are both referenced within this file, so this import is valid and necessary.


38-38: Importing new tracker interface and result type looks good.
This aligns with the new task-tracking approach introduced in this file.


63-63: Addition of trackedAskingResult is consistent with new task tracking logic.
Optional property is well-defined, but consider ensuring any thread calling code handles a missing trackedAskingResult case gracefully.


113-115: New rerunAskingTask method signature.
Adding a direct API to re-run a canceled or completed task is a solid approach. Ensure callers handle potential concurrency issues if the original task is still in progress.


118-119: New methods for retrieving asking tasks by string ID or numeric ID.
This split is understandable if the system creates tasks using different key formats. Confirm all calls properly match the correct method based on the observed ID format.


377-377: Introducing a dedicated property for askingTaskTracker.
Well-structured usage of the interface. No issues spotted.


389-389: Constructor injection of the tracker is consistent with service design.
No concerns here; this aligns with the overall dependency injection pattern.


400-400: Type annotation for askingTaskTracker is correct.
This ensures the class property remains strongly typed and consistent with the new interface.


442-442: Assigning the tracker reference is straightforward.
No issues; the property is set properly for later usage.


540-542: Optional parameters in createAskingTask implementation.
The function signature now closely matches the interface definition. Make sure to handle scenarios where these optional parameters are undefined.


550-552: Conditionally fetching asking history based on threadResponseId.
This effectively excludes canceled responses from the conversation flow. Confirm that threadResponseId definitely belongs to the correct thread in all cases.


558-559: Passing rerunFromCancelled and previousTaskId to the tracker creation.
This expands the context for re-run tasks. Looks appropriate for re-establishing continuity in the conversation history.


602-602: Cancellation of task delegated to askingTaskTracker.
This is consistent with the single responsibility principle. Exceptions bubble up as expected, aligning with the agreed-upon error-handling strategy.


610-612: New getAskingTask method.
A simple pass-through to the tracker. Error handling at a higher level is consistent with project learnings.


614-615: New getAskingTaskById method.
Mirrors the existing pattern, no issues here. Make sure usage is consistent across code references.


631-631: Using the question as the thread summary.
This is a sensible default, but ensure you revisit if there's a difference between a short summary and a full question in the future.


633-637: Storing askingTaskId from trackedAskingResult on thread creation.
Good approach for linking the response to the tracker's records. Confirm consumers handle null taskId if the property is undefined.


996-1018: New getAskingHistory method.
Filters out a canceled response if excludeThreadResponseId is supplied and excludes empty-SQL responses. This is sound for ensuring a consistent conversation flow. Verify that ignoring empty-SQL responses is always desired.

…status change more responsive to client-side
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

433-439: Expand the isResultChanged check to handle content changes.

Currently, the method only checks status changes. If the result’s data changes while the status remains the same, updates might be missed.

- if (previousResult?.status !== newResult.status) {
-   return true;
- }
+ if (
+   previousResult?.status !== newResult.status ||
+   JSON.stringify(previousResult?.response) !== JSON.stringify(newResult.response)
+ ) {
+   return true;
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e98711 and 92ee820.

📒 Files selected for processing (1)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (4)
wren-ui/src/apollo/server/models/adaptor.ts (2) (2)
  • AskResult (117:131)
  • AskInput (61:66)
wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts (1) (1)
  • IWrenAIAdaptor (46:109)
wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (2) (2)
  • IAskingTaskRepository (23:25)
  • AskingTask (12:21)
wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (1) (1)
  • IThreadResponseRepository (54:60)
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 144-144: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (3)

140-155: Potential return type mismatch with getAskingResultFromDB.

getAskingResultFromDB can return null, but getAskingResult is declared to return TrackedAskingResult. This is the same discrepancy flagged previously.

🧰 Tools
🪛 Biome (1.9.4)

[error] 144-144: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


206-240: Validate concurrency handling during parallel polling.

Multiple tasks are processed in parallel with Promise.allSettled, and runningJobs is used to guard concurrency. Confirm if external mutation of trackedTasks or repeated calls to the same queryId in quick succession could cause race conditions.

Would you like a verification script to grep for concurrent writes or to confirm that Node’s single-threaded event loop is sufficient? Let me know.


411-411: Check for null when assigning taskId.

This line may throw if this.trackedTasks.get(queryId) is undefined. A null check was previously recommended.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (3)

154-169: 🛠️ Refactor suggestion

Update getAskingResult return type to match actual behavior.

Since this method can return null (when delegating to getAskingResultFromDB), update the return type to include null to match actual behavior.

- public async getAskingResult(queryId: string): Promise<TrackedAskingResult> {
+ public async getAskingResult(queryId: string): Promise<TrackedAskingResult | null> {
🧰 Tools
🪛 Biome (1.9.4)

[error] 158-158: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


171-178: 🛠️ Refactor suggestion

Update getAskingResultById return type to match actual behavior.

Similar to getAskingResult, this method can return null but doesn't reflect that in its return type.

- public async getAskingResultById(id: number): Promise<TrackedAskingResult> {
+ public async getAskingResultById(id: number): Promise<TrackedAskingResult | null> {

425-427: 🛠️ Refactor suggestion

Check for null when updating tracked task ID.

Performing this.trackedTasks.get(queryId).taskId = task.id; can throw an error if this.trackedTasks.get(queryId) is undefined. Add a conditional check before assigning the task ID.

- this.trackedTasks.get(queryId).taskId = task.id;
+ const existingTask = this.trackedTasks.get(queryId);
+ if (existingTask) {
+   existingTask.taskId = task.id;
+ }
🧹 Nitpick comments (3)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (3)

20-29: Consider renaming taskId to pipelineId for consistency with requested changes.

The PR objectives mention changing taskId to pipeline_id. To ensure consistency with this naming convention, rename the property in the TrackedTask interface.

interface TrackedTask {
  queryId: string;
-  taskId?: number;
+  pipelineId?: number;
  lastPolled: number;
  question?: string;
  result?: AskResult;
  isFinalized: boolean;
  threadResponseId?: number;
  rerunFromCancelled?: boolean;
}

31-35: Align taskId in TrackedAskingResult with the same naming convention change.

For consistency with the previous change, also update the taskId property in the TrackedAskingResult type.

export type TrackedAskingResult = AskResult & {
-  taskId?: number;
+  pipelineId?: number;
  queryId: string;
  question: string;
};

158-165: Use optional chaining for safer property access.

Implement optional chaining for trackedTask.result to make the code more robust against potential undefined values.

- if (trackedTask && trackedTask.result) {
+ if (trackedTask?.result) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 158-158: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92ee820 and 7cf97bd.

📒 Files selected for processing (2)
  • wren-ui/src/apollo/server/services/askingService.ts (11 hunks)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
wren-ui/src/apollo/server/services/askingService.ts (2)
Learnt from: wwwy3y3
PR: Canner/WrenAI#1388
File: wren-ui/src/apollo/server/services/askingService.ts:599-604
Timestamp: 2025-03-17T19:26:10.835Z
Learning: Error handling for non-existent asking tasks in WrenAI is handled at the resolver level rather than in the service implementation.
Learnt from: wwwy3y3
PR: Canner/WrenAI#1388
File: wren-ui/src/apollo/server/services/askingService.ts:586-604
Timestamp: 2025-03-17T19:32:09.267Z
Learning: In WrenAI's askingService.ts, errors should be allowed to bubble up to the top-level error handler rather than being caught and logged at the method level.
🧬 Code Definitions (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (4)
wren-ui/src/apollo/server/models/adaptor.ts (2) (2)
  • AskResult (117:131)
  • AskInput (61:66)
wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts (1) (1)
  • IWrenAIAdaptor (46:109)
wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (2) (2)
  • IAskingTaskRepository (23:25)
  • AskingTask (12:21)
wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (1) (1)
  • IThreadResponseRepository (54:60)
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 158-158: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (7)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

379-403: 🛠️ Refactor suggestion

Update return type to include null for better type safety.

The method getAskingResultFromDB returns null when no task record is found, but the return type doesn't reflect this possibility. This mismatch could lead to runtime errors when consuming code expects a non-null value.

- private async getAskingResultFromDB({
-   queryId,
-   taskId,
- }: {
-   queryId?: string;
-   taskId?: number;
- }): Promise<TrackedAskingResult | null> {
+ private async getAskingResultFromDB({
+   queryId,
+   taskId,
+ }: {
+   queryId?: string;
+   taskId?: number;
+ }): Promise<TrackedAskingResult | null> {

Likely an incorrect or invalid review comment.

wren-ui/src/apollo/server/services/askingService.ts (6)

567-598: Well-implemented rerun functionality with proper error handling.

The new rerunAskingTask method efficiently reuses the existing task creation logic, properly sets up all required parameters, and includes appropriate error handling when a thread response isn't found.


537-565: Clean integration with the new task tracker.

The updated createAskingTask implementation properly delegates to the new askingTaskTracker service and handles the additional parameters for rerunning tasks from cancelled state. The code correctly sets up thread history for follow-up questions.


997-1019: Improved history filtering for rerun scenarios.

The enhancement to getAskingHistory to exclude specific thread responses (particularly for rerun scenarios) is a valuable improvement that prevents including cancelled responses in the history.


634-649: Thread creation now correctly handles task tracking.

The thread creation process has been updated to work with the new task tracking system, properly binding thread responses to asking tasks. This is a clean implementation that maintains the same functionality while transitioning to the new architecture.


690-705: Thread response creation mirrors the thread creation pattern.

The createThreadResponse method follows the same pattern as createThread for binding asking tasks, which maintains consistency in the codebase. This is a good example of the DRY principle.


600-617:

Details

✅ Verification successful

Updated task management methods to use askingTaskTracker.

The cancelAskingTask, getAskingTask, and getAskingTaskById methods now correctly delegate to the askingTaskTracker service while maintaining telemetry and error handling. This is aligned with the existing pattern of allowing errors to bubble up to the top-level handler rather than catching them at the service level.


🌐 Web query:

What's the best practice for error handling in TypeScript service methods - catching errors at the service level or letting them bubble up?

💡 Result:

Error handling in TypeScript service methods requires a strategic balance between localized handling and controlled propagation. Here's a structured approach based on industry practices:

Core Strategy

  1. Handle expected errors at the service level

    • Use explicit error types for known failure scenarios
    • Return typed results using Result<T, E> patterns ([3][12])
    class UserService {
      async getUser(id: number): Promise<Result<User, DomainError>> {
        try {
          return Ok(await db.fetchUser(id));
        } catch (e) {
          if (e instanceof DatabaseError) return Err(new UserNotFound());
          return Err(new ServiceUnavailable());
        }
      }
    }
  2. Bubble unexpected errors to boundaries

    • Let infrastructure/network errors propagate to centralized handlers ([7][9])
    class PaymentGateway {
      async chargeCard(card: Card) {
        // No try/catch - let fetch errors bubble
        const response = await fetch(paymentEndpoint, card);
        return processResponse(response); 
      }
    }

Best Practice Implementation

Error Boundaries

// Global error handler
process.on('uncaughtException', (error) => {
  logger.critical('Unhandled error', error); 
  metrics.trackFailure(error);
});

// API Boundary
app.use((err, req, res, next) => {
  if (err instanceof HttpError) {
    res.status(err.code).json({ error: err.message });
  } else {
    res.status(500).json({ error: 'System failure' });
  }
});

Critical Components

Aspect Service Level Handling Bubbling Strategy
Error Types Domain-specific errors Infrastructure failures
Handling Method Explicit conditional checks Top-level boundaries
Return Values Typed result objects Unmodified exceptions
Logging Contextual logging Generic error capture

Key Recommendations

  1. Adopt error hierarchies using custom ApplicationError classes ([4][10])
  2. Validate inputs thoroughly before processing ([1][4])
  3. Implement retry logic for transient errors ([5][7])
  4. Use type guards for error discrimination
function isDomainError(e: unknown): e is DomainError {
  return e instanceof DomainError;
}

The optimal approach combines explicit error handling for business-rule violations with controlled propagation of system-level exceptions. Service methods should manage errors they can meaningfully address, while allowing unexpected failures to bubble to architectural boundaries equipped with logging, monitoring, and standardized responses[5][7][9].

This strategy ensures type safety through the type system (Result types) while maintaining operational transparency via error boundaries. Developers gain compile-time validation for expected errors, while operations teams get centralized visibility into unanticipated failures.

Citations:


Updated Task Management Methods — Implementation Validated

The changes in the methods now appropriately delegate work to the askingTaskTracker service. In particular, the cancelAskingTask method captures errors only to log telemetry details before rethrowing them, ensuring that unexpected errors bubble up to the global handler. This approach is in line with best practices which recommend handling known errors locally (with associated telemetry/diagnostics) and letting unanticipated exceptions propagate. The retrieval methods similarly delegate directly without interfering with error propagation.

No further changes are needed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (2)

171-178: ⚠️ Potential issue

Match the return type to accommodate a null result.
This method may return null if the database record is missing. Modify the return type accordingly:

-public async getAskingResultById(id: number): Promise<TrackedAskingResult> {
+public async getAskingResultById(id: number): Promise<TrackedAskingResult | null> {

20-41: 🛠️ Refactor suggestion

Rename “taskId” references to “pipelineId” per PR objectives.
The PR objectives mention changing taskId to pipeline_id (or a closely aligned camelCase name). Below is an example diff to rename taskIdpipelineId and previousTaskIdpreviousPipelineId for consistency throughout these type definitions.

-interface TrackedTask {
-  queryId: string;
-  taskId?: number;
-  lastPolled: number;
-  question?: string;
-  result?: AskResult;
-  isFinalized: boolean;
-  threadResponseId?: number;
-  rerunFromCancelled?: boolean;
-}
+interface TrackedTask {
+  queryId: string;
+  pipelineId?: number;
+  lastPolled: number;
+  question?: string;
+  result?: AskResult;
+  isFinalized: boolean;
+  threadResponseId?: number;
+  rerunFromCancelled?: boolean;
+}

-export type TrackedAskingResult = AskResult & {
-  taskId?: number;
-  queryId: string;
-  question: string;
-};
+export type TrackedAskingResult = AskResult & {
+  pipelineId?: number;
+  queryId: string;
+  question: string;
+};

-export type CreateAskingTaskInput = AskInput & {
-  rerunFromCancelled?: boolean;
-  previousTaskId?: number;
-  threadResponseId?: number;
-};
+export type CreateAskingTaskInput = AskInput & {
+  rerunFromCancelled?: boolean;
+  previousPipelineId?: number;
+  threadResponseId?: number;
+};
🧹 Nitpick comments (4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (4)

17-18: Use a more conservative logging level in production.
While setting this logger to 'debug' can be useful during development, it may produce excessive logs in production environments, potentially impacting performance and cluttering log outputs.


73-74: Reduce polling frequency for improved performance.
Polling every second can lead to high overhead in production. Consider increasing the interval or making it environment-configurable, for example:

-    pollingInterval = 1000, // 1 second
+    pollingInterval = 5000, // 5 seconds

158-164: Use optional chaining for cleaner null checks.
This prevents repetitive conditions and aligns with modern TypeScript best practices.

-if (trackedTask && trackedTask.result) {
+if (trackedTask?.result) {
  return {
    ...trackedTask.result,
    queryId,
    question: trackedTask.question,
    taskId: trackedTask.taskId,
  };
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 158-158: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


448-459: Check more than just status for result changes.
Currently, isResultChanged only compares status. If other fields (e.g., generated SQL) could change, consider a deeper comparison.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7cf97bd and 8bf8f5c.

📒 Files selected for processing (1)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (4)
wren-ui/src/apollo/server/models/adaptor.ts (2) (2)
  • AskResult (117:131)
  • AskInput (61:66)
wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts (1) (1)
  • IWrenAIAdaptor (46:109)
wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (2) (2)
  • IAskingTaskRepository (23:25)
  • AskingTask (12:21)
wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (1) (1)
  • IThreadResponseRepository (54:60)
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 158-158: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (1)

43-54: Verify parameter naming alignments in IAskingTaskTracker.
If id in getAskingResultById(id: number) corresponds to a “pipelineId,” consider renaming it to match. Otherwise, clarify its usage to avoid confusion with newly introduced “pipelineId” naming.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (2)

154-183: Enhanced Retrievability of Task Results

  • The distinction between in-memory tasks via trackedTasks and database fallback through getAskingResultFromDB is well-structured.
  • A minor lint suggestion (from static analysis) indicates that line 160 could use an optional chain (if (trackedTask?.result)) instead of chained &&. This is stylistic rather than functional.
-if (trackedTask && trackedTask.result) {
+if (trackedTask?.result) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 160-160: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


414-450: Upsert-Like Behavior in updateTaskInDatabase

  • Creating a new record if a task isn’t found is intuitive for your flow.
  • Quick in-memory sync ensures subsequent lookups are consistent.

Consider adding some traces or metrics for easier debugging if creation happens unexpectedly, though not strictly necessary.

wren-ui/src/apollo/server/services/askingService.ts (1)

626-627: Comments for Multi-step Thread Creation

The inline comment clarifies the creation flow. Good to see code-based documentation for your multi-step logic.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8bf8f5c and 7fbf402.

📒 Files selected for processing (2)
  • wren-ui/src/apollo/server/services/askingService.ts (11 hunks)
  • wren-ui/src/apollo/server/services/askingTaskTracker.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
wren-ui/src/apollo/server/services/askingService.ts (2)
Learnt from: wwwy3y3
PR: Canner/WrenAI#1388
File: wren-ui/src/apollo/server/services/askingService.ts:599-604
Timestamp: 2025-03-17T19:26:10.835Z
Learning: Error handling for non-existent asking tasks in WrenAI is handled at the resolver level rather than in the service implementation.
Learnt from: wwwy3y3
PR: Canner/WrenAI#1388
File: wren-ui/src/apollo/server/services/askingService.ts:586-604
Timestamp: 2025-03-17T19:32:09.267Z
Learning: In WrenAI's askingService.ts, errors should be allowed to bubble up to the top-level error handler rather than being caught and logged at the method level.
🧬 Code Definitions (1)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (4)
wren-ui/src/apollo/server/models/adaptor.ts (2) (2)
  • AskResult (117:131)
  • AskInput (61:66)
wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts (1) (1)
  • IWrenAIAdaptor (46:109)
wren-ui/src/apollo/server/repositories/askingTaskRepository.ts (2) (2)
  • IAskingTaskRepository (23:25)
  • AskingTask (12:21)
wren-ui/src/apollo/server/repositories/threadResponseRepository.ts (1) (1)
  • IThreadResponseRepository (54:60)
🪛 Biome (1.9.4)
wren-ui/src/apollo/server/services/askingTaskTracker.ts

[error] 160-160: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (31)
wren-ui/src/apollo/server/services/askingTaskTracker.ts (10)

1-19: Imports and Logger Configuration Look Good

All necessary dependencies are imported, and the logger's debug level is appropriate for monitoring. No issues spotted in these lines.


20-36: Interfaces Provide Clear Structure

TrackedTask and TrackedAskingResult establish a helpful contract for in-memory tracking and returning data to clients. Ensuring consistent usage of these types across the codebase will enhance clarity.


37-55: Interface Cohesion

CreateAskingTaskInput and IAskingTaskTracker comprehensively define the new task creation flow and the supportive methods for retrieving/canceling tasks. The approach aligns well with typical domain-driven design patterns.


56-153: Solid Construction and Task Creation Logic

  • The constructor adequately sets default values for pollingInterval and memoryRetentionTime, and it starts polling immediately.
  • The createAskingTask method correctly:
    1. Calls the AI service to create a task.
    2. Validates parameters for reruns.
    3. Stores the task in memory for quick polling and updates.
  • Error handling is wrapped in a try/catch to avoid leaking partial states.

No immediate critical issues found. The structure is modular and clear.


184-216: Cancellation and Thread Binding

  • cancelAskingTask gracefully offloads to the wrenAIAdaptor.
  • bindThreadResponse robustly updates both in-memory and database references. Throwing an error if the task is not found is good practice.

All logic is consistent. No immediate problems noted.


218-362: Polling Mechanism is Well-Implemented

  • Regular polling with a clear interval ensures timely updates.
  • The approach of batching tasks into jobs and using Promise.allSettled is effective in a Node.js context.
  • Cleanup logic to remove stale tasks from memory helps avoid leaks.

All steps appear to handle concurrency in a single-thread environment properly. Great job keeping logic self-contained.


364-386: Thread Response Update on Finalization

  • Cleanly extracts the SQL statement from the assigned view if viewId is present.
  • Graceful fallback to direct SQL from result.response if no view is used.
  • No evident concurrency or error-handling gaps.

388-412: Database Fallback Retrieval

  • getAskingResultFromDB properly returns null if no record is found, aligning with your type signature (Promise<TrackedAskingResult | null>).
  • Logic merges the DB record with partial detail data for consistent usage.

All good.


452-459: Finalizing Task Status

  • isTaskFinalized neatly centralizes the logic to check for finishing states.
  • Maintains reliability and avoids repeating the same status checks in multiple places.

460-471: Determining Result Changes

  • isResultChanged focuses on the status difference, which is a straightforward approach.
  • For complex result comparisons, consider hashing or a deep compare if needed in the future.

No immediate adjustments needed here.

wren-ui/src/apollo/server/services/askingService.ts (21)

28-28: Introduce Project Type in Existing Import

Bringing in Project from repositories aligns well with references in the service. Nothing problematic here.


38-38: New Types from askingTaskTracker

Importing IAskingTaskTracker and TrackedAskingResult is consistent with the new architecture. Good job maintaining modular boundaries.


63-63: Track Asking Result Instead of viewId

Replacing the older approach with trackedAskingResult fosters a clearer link between the task’s progress and UI or thread updates.


101-115: Enhanced createAskingTask Signature

Adding rerunFromCancelled, previousTaskId, and threadResponseId paves the way for robust re-run flows. The inline comments clarify usage. Great approach to incorporate backward references while preserving the existing interface shape.


118-119: Return Type Improvement

getAskingTask and getAskingTaskById now return TrackedAskingResult, ensuring consistent typed responses. This is beneficial for front-end consumption.


377-378: New Tracker Property

private askingTaskTracker: IAskingTaskTracker; is introduced and injected via the constructor, improving testability and adherence to the single-responsibility principle.


389-390: Dependency Injection of askingTaskTracker

Ensuring that the tracker is provided at instantiation aligns with the overall architecture. No issues noted.


540-542: Additional Parameters for Re-run

Introducing rerunFromCancelled, previousTaskId, and threadResponseId ensures fine-grained control for canceled tasks. This design feels intuitive.


550-552: Fetching History with Exclusions

getAskingHistory is being utilized to exclude canceled thread responses if needed. Handling previous queries for re-runs is well-executed.


600-600: Cancellation Delegation

The cancelAskingTask wraps and delegates to askingTaskTracker. Clear layering. Telemetry logging is consistent with existing patterns.


611-613: Nullable Return for getAskingTask

Explicitly returning Promise<TrackedAskingResult | null> helps mitigate runtime exceptions if the record is absent. This also matches prior design patterns of letting the resolver handle the missing-task scenario.


617-619: New getAskingTaskById

This similarly returns null if the record cannot be found. Consistency with getAskingTask is appreciated.


642-643: Linking ThreadResponse and Task

The property askingTaskId is assigned from trackedAskingResult?.taskId, ensuring proper mapping. The logic is straightforward.


646-652: Binding the Task after Creation

By calling askingTaskTracker.bindThreadResponse if trackedAskingResult exists, you keep the data sources in sync. This ensures immediate reference consistency.


683-684: Assigning askingTaskId During Response Creation

Similar logic to the thread creation step. The code remains consistent. Good approach to unify how tasks link to responses.


698-699: Tracking Possibly Non-Null Task ID

Adhering to trackedAskingResult?.taskId ensures the field remains optional. No problems spotted.


701-708: Binding Task in createThreadResponse

Repeats the pattern from thread creation. This uniform approach fosters maintainability.


1001-1004: Enhanced getAskingHistory

Including an optional excludeThreadResponseId parameter eliminates unwanted queries and duplicates for re-runs. Logical and well-structured retrieval.


1008-1011: Limiting History to 10 Responses

A practical approach to reduce overhead. It helps avoid flooding the system with large histories.


1013-1018: Filtering Out Canceled or Duplicate Responses

Dynamically excluding a canceled thread response keeps the context relevant for re-runs. Proper design choice.


1021-1022: SQL Filter for Non-empty Expressiveness

Final filtering ensures the AI sees only valid SQL. This helps mitigate confusion from incomplete or empty statements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants