Skip to content
Merged
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
4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ export default {
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
'^node-fetch$': '<rootDir>/src/__mocks__/node-fetch.ts',
},
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
useESM: true,
diagnostics: {
ignoreCodes: [151002],
},
},
],
},
Expand Down
13 changes: 13 additions & 0 deletions src/__mocks__/node-fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Mock implementation of node-fetch for Jest tests
const mockFetch = jest.fn(() =>
Promise.resolve({
ok: true,
status: 200,
statusText: 'OK',
json: jest.fn(() => Promise.resolve({})),
text: jest.fn(() => Promise.resolve('')),
headers: new Map(),
})
);

export default mockFetch as unknown as typeof fetch;
3 changes: 2 additions & 1 deletion src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import dotenv from 'dotenv';
import { z } from 'zod';
import pkg from '../../package.json' with { type: 'json' };
// @ts-expect-error - ts-jest doesn't support import attributes yet
import pkg from '../../package.json';

// Load environment variables
dotenv.config();
Expand Down
22 changes: 11 additions & 11 deletions src/services/copilot-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,32 @@ export function convertMessagesToCopilotPrompt(messages: OpenAIMessage[]): strin
return '';
}

let systemPrompt = '';
let userPrompts = '';
let assistantResponses = '';
let prompt = '';

// Process messages in order to construct a coherent prompt
// Process messages in order to maintain conversation flow
for (const message of messages) {
if (!message.role || !message.content) continue;

switch (message.role) {
case 'system':
systemPrompt += message.content + '\n\n';
prompt += message.content + '\n\n';
break;
case 'user':
userPrompts += 'User: ' + message.content + '\n\n';
prompt += 'User: ' + message.content + '\n\n';
break;
case 'assistant':
assistantResponses += 'Assistant: ' + message.content + '\n\n';
prompt += 'Assistant: ' + message.content + '\n\n';
break;
}
}

// Ensure it ends with a user message to prompt a response
// Ensure it ends with a prompt for the assistant if the last message is from user
const lastMessage = messages[messages.length - 1];
const needsAssistantPrompt = lastMessage.role !== 'user';
if (lastMessage.role === 'user') {
prompt += 'Assistant: ';
}

return systemPrompt + userPrompts + assistantResponses + (needsAssistantPrompt ? '' : 'Assistant: ');
return prompt;
}

/**
Expand Down Expand Up @@ -73,7 +73,7 @@ export function detectLanguageFromMessages(messages: OpenAIMessage[]): string {
}

// Check for file extensions in the message
const fileExtensionMatch = content.match(/\.([a-zA-Z0-9]+)(?:\s|"|')/);
const fileExtensionMatch = content.match(/\.([a-zA-Z0-9]+)(?:\s|"|'|\?|$)/);
if (fileExtensionMatch && fileExtensionMatch[1]) {
const ext = fileExtensionMatch[1].toLowerCase();
const extToLang: Record<string, string> = {
Expand Down