feat: pipeline builder UI — visual config wizard (#8)#8
Merged
CIKR-Repos merged 2 commits intomainfrom Feb 18, 2026
Merged
Conversation
…model selection, status monitoring
Reviewer's GuideImplements a visual, step-based pipeline builder UI with drag-and-drop blocks and a backing PipelineService that loads/saves pipeline config and related data via APIs, wires it into the pipeline route, and fixes QueryEngineService to include the latest user message when building chat history. Sequence diagram for loading and saving pipeline configurationsequenceDiagram
actor User
participant Router as AngularRouter
participant PipelineComponent
participant PipelineService
participant HttpClient
participant ApiServer
User->>Router: Navigate to /projects/:projectId/pipeline
Router->>PipelineComponent: Create component instance
PipelineComponent->>PipelineComponent: ngOnInit()
PipelineComponent->>PipelineService: loadPipeline(projectId)
PipelineService->>PipelineService: isLoading = true
PipelineService->>HttpClient: GET /api/projects/projectId/pipelines
HttpClient-->>PipelineService: PipelineResponse[]
PipelineService->>PipelineService: pipeline, config, savedConfig signals updated
PipelineService->>HttpClient: GET /api/projects/projectId/documents
HttpClient-->>PipelineService: DocumentInfo[]
PipelineService->>PipelineService: documents signal updated
PipelineService->>HttpClient: GET /api/models
HttpClient-->>PipelineService: ModelSelection
PipelineService->>PipelineService: models signal updated
PipelineService->>PipelineService: isLoading = false
User->>PipelineComponent: Edit config fields
PipelineComponent->>PipelineService: updateConfig(partialConfig)
PipelineService->>PipelineService: config signal updated
PipelineService->>PipelineService: hasUnsavedChanges computed true
User->>PipelineComponent: Click Save
PipelineComponent->>PipelineService: savePipeline(projectId)
PipelineService->>PipelineService: isSaving = true, saveError = null
PipelineService->>HttpClient: PUT /api/projects/projectId/pipelines/pipelineId
HttpClient-->>PipelineService: Updated PipelineResponse
PipelineService->>PipelineService: pipeline, savedConfig, config signals updated
PipelineService->>PipelineService: isSaving = false
Sequence diagram for chunk preview loading in pipeline buildersequenceDiagram
actor User
participant PipelineComponent
participant PipelineService
participant HttpClient
participant ApiServer
User->>PipelineComponent: Select document for chunk preview
PipelineComponent->>PipelineService: loadChunkPreview(projectId, documentId)
PipelineService->>PipelineService: Read current config (chunkSize, chunkOverlap)
PipelineService->>HttpClient: GET /api/projects/projectId/documents/documentId/chunks
note right of HttpClient: Query params
HttpClient-->>ApiServer: chunkSize, chunkOverlap, page=1, pageSize=3
ApiServer-->>HttpClient: ChunkPreviewResponse
HttpClient-->>PipelineService: ChunkPreviewResponse
PipelineService->>PipelineService: chunkPreview signal updated
PipelineService-->>PipelineComponent: Updated chunk preview state rendered
Sequence diagram for updated QueryEngineService chat history buildingsequenceDiagram
participant Client
participant QueryEngineService
participant Memory as ConversationMemory
participant KernelFactory
participant ChatService as IChatCompletionService
Client->>QueryEngineService: QueryAsync(sessionId, userMessage, sources, models)
QueryEngineService->>Memory: GetConversationWindowAsync(sessionId)
Memory-->>QueryEngineService: conversationHistory
QueryEngineService->>KernelFactory: BuildChatKernel(models.ChatModel)
KernelFactory-->>QueryEngineService: Kernel
QueryEngineService->>QueryEngineService: BuildChatHistory(conversationHistory, sources, userMessage)
QueryEngineService->>ChatService: GetChatMessageContentAsync(chatHistory)
ChatService-->>QueryEngineService: ChatResponseContent
QueryEngineService-->>Client: ChatResponse
Client->>QueryEngineService: QueryStreamAsync(sessionId, userMessage, sources, models)
QueryEngineService->>Memory: GetConversationWindowAsync(sessionId)
Memory-->>QueryEngineService: conversationHistory
QueryEngineService->>KernelFactory: BuildChatKernel(models.ChatModel)
KernelFactory-->>QueryEngineService: Kernel
QueryEngineService->>QueryEngineService: BuildChatHistory(conversationHistory, sources, userMessage)
QueryEngineService->>ChatService: GetStreamingChatMessageContents(chatHistory)
ChatService-->>QueryEngineService: ChatStreamChunk*
QueryEngineService-->>Client: ChatStreamChunk*
Class diagram for PipelineComponent and PipelineServiceclassDiagram
class PipelineConfig {
+number chunkSize
+number chunkOverlap
+string chunkingStrategy
+string embeddingModel
+number embeddingDimensions
+string retrievalStrategy
+number topK
+number scoreThreshold
+string generationModel
+number temperature
+number maxTokens
+string systemPrompt
}
class PipelineResponse {
+string id
+string projectId
+string name
+string description
+PipelineConfig config
+string status
+string createdAt
+string updatedAt
}
class DocumentInfo {
+string id
+string fileName
+string fileType
+number fileSize
+string status
}
class ChunkPreviewItem {
+string content
+number tokenCount
+number index
}
class ChunkPreviewResponse {
+ChunkPreviewItem[] chunks
+number totalCount
+number page
+number pageSize
}
class ModelSelection {
+string embeddingModel
+number embeddingDimensions
+string chatModel
+number maxTokensPerRequest
+number maxDocumentsPerProject
}
class PipelineService {
-HttpClient http
+pipeline signal~PipelineResponse|
+config signal~PipelineConfig|
+savedConfig signal~PipelineConfig|
+documents signal~DocumentInfo[]|
+models signal~ModelSelection|
+chunkPreview signal~ChunkPreviewResponse|
+isSaving signal~boolean|
+isLoading signal~boolean|
+saveError signal~string|
+hasUnsavedChanges computed~boolean|
+loadPipeline(projectId string) Promise~void|
+savePipeline(projectId string) Promise~void|
+resetDefaults() void
+updateConfig(partial PipelineConfig) void
+loadChunkPreview(projectId string, documentId string) Promise~void|
}
class PipelineComponent {
-ActivatedRoute route
+PipelineService svc
-string projectId
+ngOnInit() void
+onDrop(event CdkDragDrop) void
+save() void
+blockClass(block PipelineBlock) string
+blockIconBg(block PipelineBlock) string
+blockTypeBadge(block PipelineBlock) string
+blockSummary(block PipelineBlock) string
+onConfigChange(blockId string, key string, event Event) void
+onConfigChangeNum(blockId string, key string, event Event) void
+onConfigChangeFloat(blockId string, key string, event Event) void
+onConfigChangeBool(blockId string, key string, event Event) void
}
class PipelineBlock {
+string id
+BlockType type
+Record config
}
class BlockType {
}
PipelineService --> PipelineConfig
PipelineService --> PipelineResponse
PipelineService --> DocumentInfo
PipelineService --> ChunkPreviewResponse
PipelineService --> ModelSelection
PipelineComponent --> PipelineService
PipelineComponent --> PipelineBlock
PipelineBlock --> BlockType
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Owner
Author
|
@copilot please review this PR |
|
@CIKR-Repos I've opened a new pull request, #9, to work on those changes. Once the pull request is ready, I'll request review from you. |
9 tasks
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The
PipelineComponentimportsPipelineServicefrom./pipeline.service, but the new service was added underfeatures/pipeline-builder/pipeline.service.ts; double-check that the import path and file location are aligned so the component actually uses the intended service. - Since
PipelineServiceis already markedprovidedIn: 'root', adding it again inPipelineComponent.providerswill create a separate instance and can lead to confusing state; consider removing the component-level provider unless you explicitly need an isolated instance. - The numeric config change handlers (
onConfigChangeNumandonConfigChangeFloat) directly useparseInt/parseFloatwithout handlingNaN, which can push invalid values into the config; consider guarding against empty/invalid input and either reverting to the previous value or using a safe default.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `PipelineComponent` imports `PipelineService` from `./pipeline.service`, but the new service was added under `features/pipeline-builder/pipeline.service.ts`; double-check that the import path and file location are aligned so the component actually uses the intended service.
- Since `PipelineService` is already marked `providedIn: 'root'`, adding it again in `PipelineComponent.providers` will create a separate instance and can lead to confusing state; consider removing the component-level provider unless you explicitly need an isolated instance.
- The numeric config change handlers (`onConfigChangeNum` and `onConfigChangeFloat`) directly use `parseInt/parseFloat` without handling `NaN`, which can push invalid values into the config; consider guarding against empty/invalid input and either reverting to the previous value or using a safe default.
## Individual Comments
### Comment 1
<location> `client/src/app/pages/pipeline/pipeline.ts:76-78` </location>
<code_context>
+ this.svc.updateBlockConfig(blockId, key, el.value);
+ }
+
+ onConfigChangeNum(blockId: string, key: string, event: Event) {
+ const el = event.target as HTMLInputElement;
+ this.svc.updateBlockConfig(blockId, key, parseInt(el.value, 10));
+ }
+
</code_context>
<issue_to_address>
**issue:** Handle NaN cases when parsing numeric config values from inputs.
If the input is cleared or contains non-numeric characters, `parseInt`/`parseFloat` will return `NaN`, which will then be stored in the config and may break UI or backend logic. Consider coercing empty values to the previous/default value, clamping to a safe fallback, or skipping the update when the parsed value is `NaN`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pipeline Builder UI
What
Tech
Files Changed
PR #8 of 10 — Pipeline Builder UI
Summary by Sourcery
Introduce a visual pipeline builder UI with configurable RAG stages and supporting backend/API integration updates.
New Features:
Enhancements:
Documentation: