Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app/analytics/ai-analytics/ai-analytics.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { environment } from '../../../environments/environment';
import { authHeaders } from '../../shared/services/auth-fetch';

@Component({
selector: 'app-ai-analytics',
Expand All @@ -18,7 +19,7 @@ export class AiAnalyticsComponent implements OnInit {

fetchUsage() {
this.loading = true;
fetch(`${environment.SERVER_URL}/rag-analytics/adhoc-usage`)
fetch(`${environment.SERVER_URL}/rag-analytics/adhoc-usage`, { headers: authHeaders() })
.then(res => res.json())
.then(data => {
this.usage = data;
Expand Down
5 changes: 2 additions & 3 deletions src/app/analytics/ai-pipeline/ai-pipeline.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { authHeaders } from '../../shared/services/auth-fetch';

interface AgentPrompt {
role: string;
Expand Down Expand Up @@ -184,9 +185,7 @@ Return ONLY valid JSON:

fetch('/api/rag-analytics/playground/analyze', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ text: this.playgroundText })
})
.then(response => {
Expand Down
27 changes: 14 additions & 13 deletions src/app/analytics/ai-playground/ai-playground.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';
import { environment } from '../../../environments/environment';
import { authHeaders } from '../../shared/services/auth-fetch';

interface PipelineStage {
id: string;
Expand Down Expand Up @@ -146,7 +147,7 @@ export class AiPlaygroundComponent {

fetch(`${environment.SERVER_URL}/rag-analytics/playground/generate-prompt`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ description: stage.userDescription })
})
.then(res => res.json())
Expand All @@ -166,7 +167,7 @@ export class AiPlaygroundComponent {

// Stage Library
fetchSavedStages() {
fetch(`${environment.SERVER_URL}/rag-analytics/stages`)
fetch(`${environment.SERVER_URL}/rag-analytics/stages`, { headers: authHeaders() })
.then(res => res.json())
.then(data => { this.savedStages = Array.isArray(data) ? data : []; })
.catch(() => { this.savedStages = []; });
Expand All @@ -175,7 +176,7 @@ export class AiPlaygroundComponent {
saveStageToLibrary(stage: PipelineStage) {
fetch(`${environment.SERVER_URL}/rag-analytics/stages`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({
stage_id: stage.id,
name: stage.name,
Expand Down Expand Up @@ -208,7 +209,7 @@ export class AiPlaygroundComponent {
}

deleteSavedStage(stageId: string) {
fetch(`${environment.SERVER_URL}/rag-analytics/stages/${stageId}`, { method: 'DELETE' })
fetch(`${environment.SERVER_URL}/rag-analytics/stages/${stageId}`, { method: 'DELETE', headers: authHeaders() })
.then(() => this.fetchSavedStages())
.catch(err => console.error('Failed to delete stage:', err));
}
Expand All @@ -220,7 +221,7 @@ export class AiPlaygroundComponent {
// Generate prompt from description
fetch(`${environment.SERVER_URL}/rag-analytics/playground/generate-prompt`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ description: this.newStageDescription })
})
.then(res => res.json())
Expand All @@ -229,7 +230,7 @@ export class AiPlaygroundComponent {
// Generate examples
return fetch(`${environment.SERVER_URL}/rag-analytics/stages/generate-examples`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ system_prompt: systemPrompt, user_description: this.newStageDescription })
})
.then(res => res.json())
Expand All @@ -239,7 +240,7 @@ export class AiPlaygroundComponent {
// Save to DB
return fetch(`${environment.SERVER_URL}/rag-analytics/stages`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({
stage_id: stageId,
name,
Expand Down Expand Up @@ -268,7 +269,7 @@ export class AiPlaygroundComponent {
generateExamples(stage: PipelineStage) {
fetch(`${environment.SERVER_URL}/rag-analytics/stages/generate-examples`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ system_prompt: stage.systemPrompt, user_description: stage.userDescription })
})
.then(res => res.json())
Expand All @@ -284,7 +285,7 @@ export class AiPlaygroundComponent {

// Pipeline Templates
fetchSavedPipelines() {
fetch(`${environment.SERVER_URL}/rag-analytics/pipelines`)
fetch(`${environment.SERVER_URL}/rag-analytics/pipelines`, { headers: authHeaders() })
.then(res => res.json())
.then(data => { this.savedPipelines = Array.isArray(data) ? data : []; })
.catch(() => { this.savedPipelines = []; });
Expand All @@ -300,7 +301,7 @@ export class AiPlaygroundComponent {

fetch(`${environment.SERVER_URL}/rag-analytics/pipelines`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({
template_id: templateId,
name: this.savePipelineName,
Expand Down Expand Up @@ -330,7 +331,7 @@ export class AiPlaygroundComponent {
}

deleteSavedPipeline(templateId: string) {
fetch(`${environment.SERVER_URL}/rag-analytics/pipelines/${templateId}`, { method: 'DELETE' })
fetch(`${environment.SERVER_URL}/rag-analytics/pipelines/${templateId}`, { method: 'DELETE', headers: authHeaders() })
.then(() => this.fetchSavedPipelines())
.catch(err => console.error('Failed to delete pipeline:', err));
}
Expand Down Expand Up @@ -358,7 +359,7 @@ export class AiPlaygroundComponent {

fetch(`${environment.SERVER_URL}/rag-analytics/playground/execute-stage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({
type: stage.type,
systemPrompt: stage.systemPrompt,
Expand Down Expand Up @@ -449,7 +450,7 @@ export class AiPlaygroundComponent {

const apiUrl = `${environment.SERVER_URL}/rag-analytics/playground/execute-pipeline`;

fetch(apiUrl, { method: 'POST', body: formData })
fetch(apiUrl, { method: 'POST', headers: authHeaders(), body: formData })
.then(response => {
const reader = response.body!.getReader();
const decoder = new TextDecoder();
Expand Down
3 changes: 2 additions & 1 deletion src/app/home/home/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Title } from '@angular/platform-browser';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
import { environment } from '../../../environments/environment';
import { Section508Clause, resolveClause, clauseToPlainText } from '../../shared/section508-clause';
import { authHeaders } from '../../shared/services/auth-fetch';

@Component({
selector: 'app-home',
Expand Down Expand Up @@ -376,7 +377,7 @@ export class HomeComponent
try {
const response = await fetch(`${environment.SERVER_URL}/rag-analytics/playground/package-synthesis`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({
summaries,
file_count: fileNames.length,
Expand Down
19 changes: 19 additions & 0 deletions src/app/shared/services/auth-fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Authorization headers for raw fetch() calls.
*
* Angular's HttpClient gets its bearer token from TokenInterceptor, but raw
* fetch() bypasses the interceptor entirely. Any fetch() to an authenticated
* SRT endpoint has to attach the header itself, and this is the one place that
* knows how.
*
* Prefer HttpClient where practical. fetch() is used in a few places for
* streaming responses and multipart uploads, which is where this helper applies.
*
* @param extra additional headers to merge, for example Content-Type. Omit
* Content-Type entirely when sending FormData so the browser can
* set the multipart boundary itself.
*/
export function authHeaders (extra: Record<string, string> = {}): Record<string, string> {
const token = localStorage.getItem('token')
return token ? { ...extra, Authorization: `Bearer ${token}` } : { ...extra }
}