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
32 changes: 17 additions & 15 deletions workspaces/lightspeed/e2e-tests/fixtures/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,23 +283,25 @@ export function generateQueryResponseWithMcpToolCall(
request_id: mockStreamRequestId,
},
});
events.push({
event: 'tool_call',
data: {
id: e2eMcpToolCallId,
name: 'mcp_list_tools',
args: { server_label: 'mcp-integration-tools' },
type: 'mcp_list_tools',
events.push(
{
event: 'tool_call',
data: {
id: e2eMcpToolCallId,
name: 'mcp_list_tools',
args: { server_label: 'mcp-integration-tools' },
type: 'mcp_list_tools',
},
},
});
events.push({
event: 'tool_result',
data: {
id: e2eMcpToolCallId,
status: 'success',
content: '{"server_label":"mcp-integration-tools","tools":[]}',
{
event: 'tool_result',
data: {
id: e2eMcpToolCallId,
status: 'success',
content: '{"server_label":"mcp-integration-tools","tools":[]}',
},
},
});
);

const tokens = assistantResponse.match(/(\s+|[^\s]+)/g) || [
assistantResponse,
Expand Down
5 changes: 3 additions & 2 deletions workspaces/lightspeed/e2e-tests/utils/accessibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function runAccessibilityTests(
page: Page,
testInfo: TestInfo,
attachName = 'accessibility-scan-results.json',
options: { skipFailures?: boolean } = { skipFailures: true },
options?: { skipFailures?: boolean },
) {
const accessibilityScanResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
Expand All @@ -32,7 +32,8 @@ export async function runAccessibilityTests(
contentType: 'application/json',
});

if (!options?.skipFailures) {
const { skipFailures = true } = options ?? {};
if (!skipFailures) {
expect(
accessibilityScanResults.violations,
'Accessibility violations found',
Expand Down
2 changes: 1 addition & 1 deletion workspaces/lightspeed/e2e-tests/utils/devMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export type MockMcpServersOptions = {
let mcpMockOptions: MockMcpServersOptions = {};

function cloneMcpServersMock(json: McpServersListMock): McpServersListMock {
return JSON.parse(JSON.stringify(json)) as McpServersListMock;
return structuredClone(json);
}

export async function mockModels(page: Page, models: any[]) {
Expand Down
2 changes: 1 addition & 1 deletion workspaces/lightspeed/e2e-tests/utils/testHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export async function assertClipboardContains(
expectedText: string,
) {
const clipboardText = await page.evaluate(() =>
window.navigator.clipboard.readText(),
globalThis.navigator.clipboard.readText(),
);
expect(clipboardText).toMatch(expectedText);
}
6 changes: 3 additions & 3 deletions workspaces/lightspeed/e2e-tests/utils/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ export function formatMcpSelectedCount(
totalCount: number,
): string {
return t['mcp.settings.selectedCount']
.replace(/\{\{selectedCount\}\}/g, String(selectedCount))
.replace(/\{\{totalCount\}\}/g, String(totalCount));
.replaceAll('{{selectedCount}}', String(selectedCount))
.replaceAll('{{totalCount}}', String(totalCount));
}

/** Status cell detail for a connected server tool count (singular vs plural). */
Expand All @@ -79,5 +79,5 @@ export function formatMcpToolCountStatus(
toolCount === 1
? 'mcp.settings.status.oneTool'
: 'mcp.settings.status.manyTools';
return t[key].replace(/\{\{count\}\}/g, String(toolCount));
return t[key].replaceAll('{{count}}', String(toolCount));
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ export const mockFile1 = {

// In-memory storage for tests
const vectorStores = new Map<string, any>();
const files = new Map<string, any>();
const vectorStoreFiles = new Map<string, any[]>();

/** Monotonic suffix so vector store IDs never collide when Date.now() repeats (fast CI). */
Expand All @@ -78,7 +77,6 @@ let nextFileSeq = 0;

export function resetMockStorage() {
vectorStores.clear();
files.clear();
vectorStoreFiles.clear();
nextVectorStoreSeq = 0;
nextFileSeq = 0;
Expand All @@ -91,7 +89,7 @@ export function resetMockStorage() {
export const lightspeedCoreHandlers: HttpHandler[] = [
// Create vector store
http.post(`${LIGHTSPEED_CORE_ADDR}/v1/vector-stores`, async ({ request }) => {
const body = (await request.json()) as any;
const body: any = await request.json();
const id = `vs-${Date.now()}-${nextVectorStoreSeq++}`;
const vectorStore = {
id,
Expand Down Expand Up @@ -131,7 +129,7 @@ export const lightspeedCoreHandlers: HttpHandler[] = [
{ status: 404 },
);
}
const body = (await request.json()) as any;
const body: any = await request.json();
const updated = {
...vectorStore,
metadata: body.metadata || vectorStore.metadata,
Expand Down Expand Up @@ -169,7 +167,6 @@ export const lightspeedCoreHandlers: HttpHandler[] = [
created_at: Date.now(),
purpose: 'assistants',
};
files.set(fileId, file);
return HttpResponse.json(file);
}),

Expand All @@ -186,7 +183,7 @@ export const lightspeedCoreHandlers: HttpHandler[] = [
);
}

const body = (await request.json()) as any;
const body: any = await request.json();
const vectorStoreFile = {
id: body.file_id,
status: 'completed' as const,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ describe('McpServerValidator auth header behavior', () => {
};
childMock.mockImplementation(() => logger);

const originalFetch = global.fetch;
const originalFetch = globalThis.fetch;

afterEach(() => {
global.fetch = originalFetch;
globalThis.fetch = originalFetch;
jest.clearAllMocks();
});

it('tries raw token first, then Bearer on 401/403', async () => {
const fetchMock = jest
.fn()
.mockResolvedValue(new Response(null, { status: 401 }));
global.fetch = fetchMock;
globalThis.fetch = fetchMock;

const validator = new McpServerValidator(logger);
const result = await validator.validate(url, 'raw-token');
Expand All @@ -63,7 +63,7 @@ describe('McpServerValidator auth header behavior', () => {
const fetchMock = jest
.fn()
.mockResolvedValue(new Response(null, { status: 401 }));
global.fetch = fetchMock;
globalThis.fetch = fetchMock;

const validator = new McpServerValidator(logger);
const result = await validator.validate(url, 'Basic abc123');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ async function handleHttpError(
*/
export class VectorStoresOperator {
private static instance: VectorStoresOperator | null = null;
private baseURL: string;
private logger: LoggerService;
private readonly baseURL: string;
private readonly logger: LoggerService;

private constructor(lightspeedCoreUrl: string, logger: LoggerService) {
this.baseURL = lightspeedCoreUrl;
Expand All @@ -114,12 +114,10 @@ export class VectorStoresOperator {
lightspeedCoreUrl: string,
logger: LoggerService,
): VectorStoresOperator {
if (!VectorStoresOperator.instance) {
VectorStoresOperator.instance = new VectorStoresOperator(
lightspeedCoreUrl,
logger,
);
}
VectorStoresOperator.instance ??= new VectorStoresOperator(
lightspeedCoreUrl,
logger,
);
return VectorStoresOperator.instance;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe('documentHelpers', () => {

describe('parseFileContent', () => {
it('should throw error when no file uploaded for non-URL type', async () => {
await expect(parseFileContent(logger, 'txt', undefined)).rejects.toThrow(
await expect(parseFileContent(logger, 'txt')).rejects.toThrow(
'No file uploaded',
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import { InputError } from '@backstage/errors';

import { Parser } from 'htmlparser2';

import dns from 'dns/promises';
import { isIP } from 'net';
import dns from 'node:dns/promises';
import { isIP } from 'node:net';

import {
DEFAULT_MAX_FILE_SIZE_MB,
Expand Down Expand Up @@ -163,7 +163,7 @@ const isPrivateOrInternalIP = (ip: string): boolean => {
// Extract the hex parts and check against private ranges
const parts = ipv4Part.split(':');
if (parts.length >= 1) {
const firstHex = parseInt(parts[0], 16);
const firstHex = Number.parseInt(parts[0], 16);
// Check for common private ranges in hex:
// 127.x.x.x -> 0x7F00-0x7FFF (loopback)
// 10.x.x.x -> 0x0A00-0x0AFF (private)
Expand Down Expand Up @@ -293,7 +293,7 @@ export const sanitizeContentForRAG = (content: string): string => {

// Limit excessive consecutive newlines to prevent context stuffing
const newlinePattern = new RegExp(
`\\n{${MAX_CONSECUTIVE_NEWLINES + 1},}`,
String.raw`\n{${MAX_CONSECUTIVE_NEWLINES + 1},}`,
'g',
);
sanitized = sanitized.replace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ import { toFile } from './fileParser';
* Uses VectorStoresOperator to proxy through lightspeed-core
*/
export class DocumentService {
private logger: LoggerService;
private client: VectorStoresOperator;
private chunkingStrategy: {
private readonly logger: LoggerService;
private readonly client: VectorStoresOperator;
private readonly chunkingStrategy: {
type: string;
static?: { max_chunk_size_tokens: number; chunk_overlap_tokens: number };
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { InputError } from '@backstage/errors';
import * as yaml from 'js-yaml';
import * as pdfjsLib from 'pdfjs-dist';

import { Readable } from 'stream';
import { Readable } from 'node:stream';

import { SupportedFileType } from '../../constant';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import express, { Router } from 'express';

import { lightspeedNotebooksUsePermission } from '@red-hat-developer-hub/backstage-plugin-lightspeed-common';

import { Readable, Transform } from 'stream';
import { Readable, Transform } from 'node:stream';

import {
DEFAULT_LIGHTSPEED_SERVICE_HOST,
Expand Down Expand Up @@ -232,8 +232,6 @@ export async function createNotebooksRouter(
);

// Extract citations/sources from tool calls (file_search results)

// this.push(`data: ${JSON.stringify(legacy)}\n\n`);
} else {
// Log unhandled event types to help identify what we're missing
logger.debug(`Unhandled SSE event type: ${eventType}`, parsed);
Expand Down Expand Up @@ -507,7 +505,7 @@ export async function createNotebooksRouter(
}

if (!response.ok) {
const errorBody = (await response.json()) as any;
const errorBody = await response.json();
const errorMsg =
errorBody?.detail?.[0]?.msg ||
errorBody?.detail?.cause ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import { VectorStoresOperator } from '../VectorStoresOperator';
* - Uses VectorStoresOperator to proxy through lightspeed-core
*/
export class SessionService {
private logger: LoggerService;
private client: VectorStoresOperator;
private providerId: string;
private readonly logger: LoggerService;
private readonly client: VectorStoresOperator;
private readonly providerId: string;

constructor(client: VectorStoresOperator, logger: LoggerService) {
this.client = client;
Expand Down Expand Up @@ -157,10 +157,9 @@ export class SessionService {

const updated: NotebookSession = {
...existing,
name: name !== undefined ? name : existing.name,
description:
description !== undefined ? description : existing.description,
metadata: metadata !== undefined ? metadata : existing.metadata,
name: name ?? existing.name,
description: description ?? existing.description,
metadata: metadata ?? existing.metadata,
updated_at: new Date().toISOString(),
};

Expand Down
Loading
Loading