Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
80ee423
Update GitHub Actions workflow configuration
Gerome-Elassaad Nov 22, 2025
14ab51b
Update ControlPanelDialog component
Gerome-Elassaad Nov 22, 2025
4ea4143
Update ControlPanelContent component
Gerome-Elassaad Nov 22, 2025
52d3b76
Update Chatbox component
Gerome-Elassaad Nov 22, 2025
bd2af60
Update GitCloneButton component
Gerome-Elassaad Nov 22, 2025
4d4ccce
Update Markdown spec tests
Gerome-Elassaad Nov 22, 2025
080e268
Update Markdown component
Gerome-Elassaad Nov 22, 2025
a5f9166
Update UserMessage component
Gerome-Elassaad Nov 22, 2025
f22c5c8
Update GitUrlImport client component
Gerome-Elassaad Nov 22, 2025
3841f29
Update MCPDialog component
Gerome-Elassaad Nov 22, 2025
75fc21f
Update MCPContent component
Gerome-Elassaad Nov 22, 2025
c6b4034
Update create-summary LLM utility
Gerome-Elassaad Nov 22, 2025
6b3b77a
Update select-context LLM utility
Gerome-Elassaad Nov 22, 2025
05d97f1
Update stream-text LLM utility
Gerome-Elassaad Nov 22, 2025
fadecfb
Update LLM utils
Gerome-Elassaad Nov 22, 2025
34eff03
Update chat-prompt configuration
Gerome-Elassaad Nov 22, 2025
d81f3d2
Update fine-tuned prompts
Gerome-Elassaad Nov 22, 2025
dd515a8
Update optimized prompts
Gerome-Elassaad Nov 22, 2025
77a61e5
Update prompts configuration
Gerome-Elassaad Nov 22, 2025
85a9b26
Update Amazon Bedrock provider
Gerome-Elassaad Nov 22, 2025
9a39b71
Update Anthropic provider
Gerome-Elassaad Nov 22, 2025
60e448e
Update Cohere provider
Gerome-Elassaad Nov 22, 2025
aa91866
Update DeepSeek provider
Gerome-Elassaad Nov 22, 2025
53ff10e
Update Google provider
Gerome-Elassaad Nov 22, 2025
56bd0a4
Update Groq provider
Gerome-Elassaad Nov 22, 2025
455c3b1
Update HuggingFace provider
Gerome-Elassaad Nov 22, 2025
1c304c8
Update Hyperbolic provider
Gerome-Elassaad Nov 22, 2025
fa09241
Update LMStudio provider
Gerome-Elassaad Nov 22, 2025
6291a52
Update Mistral provider
Gerome-Elassaad Nov 22, 2025
5dd4e46
Update Moonshot provider
Gerome-Elassaad Nov 22, 2025
64b681b
Update Ollama provider
Gerome-Elassaad Nov 22, 2025
01add35
Update OpenRouter provider
Gerome-Elassaad Nov 22, 2025
f801685
Update OpenAI-like provider
Gerome-Elassaad Nov 22, 2025
7641206
Update OpenAI provider
Gerome-Elassaad Nov 22, 2025
730ccba
Update Perplexity provider
Gerome-Elassaad Nov 22, 2025
104c5b0
Update Together provider
Gerome-Elassaad Nov 22, 2025
fe86dd6
Update xAI provider
Gerome-Elassaad Nov 22, 2025
cac8232
Update message-parser spec tests
Gerome-Elassaad Nov 22, 2025
cf15863
Update message-parser runtime
Gerome-Elassaad Nov 22, 2025
21ba9da
Update chat API route
Gerome-Elassaad Nov 22, 2025
09dc9e0
Update artifact types
Gerome-Elassaad Nov 22, 2025
922286c
Update fileUtils
Gerome-Elassaad Nov 22, 2025
41fa17a
Update folderImport utility
Gerome-Elassaad Nov 22, 2025
e4e0810
Update markdown utility
Gerome-Elassaad Nov 22, 2025
fa2a3c7
Update projectCommands utility
Gerome-Elassaad Nov 22, 2025
1296c4a
Update selectStarterTemplate utility
Gerome-Elassaad Nov 22, 2025
1a57bc2
Update electron-builder configuration
Gerome-Elassaad Nov 22, 2025
318f4c7
bump version > v1.1.12
Gerome-Elassaad Nov 22, 2025
0ce1c75
update api version to 1.1.12
Gerome-Elassaad Nov 22, 2025
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
37 changes: 10 additions & 27 deletions .github/workflows/electron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,38 +79,21 @@ jobs:
fi
shell: bash

# Upload artifacts
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }}-build
path: |
dist/*.exe
dist/*.dmg
dist/*.deb
dist/*.AppImage
dist/*.zip
if-no-files-found: ignore

release:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' || github.ref_type == 'tag'

steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true

# Create Release
- name: Create Release
uses: softprops/action-gh-release@v2
with:
# Use the workflow_dispatch input tag if available, else use the Git ref name.
tag_name: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
draft: false
# Only branch pushes remain drafts. For workflow_dispatch and tag pushes the release is published.
draft: ${{ github.event_name != 'workflow_dispatch' && github.ref_type == 'branch' }}
# For tag pushes, name the release as "Release <tagname>", otherwise "Electron Release".
name: ${{ (github.event_name == 'push' && github.ref_type == 'tag') && format('Release {0}', github.ref_name) || 'Electron Release' }}
files: |
artifacts/**/*
dist/*.exe
dist/*.dmg
dist/*.deb
dist/*.AppImage
dist/*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function ControlPanelDialog({ isOpen, onClose, initialTab = 'settings' }:
)}
aria-label="Close settings"
>
<div className="i-heroicons:x-mark-solid w-4 h-4" />
<div className="i-lucide:x w-4 h-4" />
</button>
</RadixDialog.Close>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function TabContent({ tab }: { tab: TabType }) {
return (
<div className="flex items-center justify-center h-full text-codinit-elements-textSecondary">
<div className="text-center">
<div className="i-heroicons:exclamation-triangle w-12 h-12 mx-auto mb-4 opacity-50" />
<div className="i-lucide:alert-triangle w-12 h-12 mx-auto mb-4 opacity-50" />
<p className="text-sm">Tab not found</p>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components/chat/Chatbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ export const ChatBox: React.FC<ChatBoxProps> = (props) => {
</div>

{/* MCP Integration Panel */}
<MCPDialog isOpen={isMcpPanelOpen} onClose={() => setIsMcpPanelOpen(false)} />
<MCPDialog isOpen={isMcpPanelOpen} onClose={() => setIsMcpPanelOpen(false)} initialTab="marketplace" />
</>
);
};
12 changes: 6 additions & 6 deletions app/components/chat/GitCloneButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ignore from 'ignore';
import { useGit } from '~/lib/hooks/useGit';
import type { Message } from 'ai';
import { detectProjectCommands, createCommandsMessage, escapeExampleTags } from '~/utils/projectCommands';
import { detectProjectCommands, createCommandsMessage, escapeCodinitTags } from '~/utils/projectCommands';
import { generateId } from '~/utils/fileUtils';
import { useState } from 'react';
import { toast } from 'react-toastify';
Expand Down Expand Up @@ -119,16 +119,16 @@ ${skippedFiles.map((f) => `- ${f}`).join('\n')}`
: ''
}

<exampleArtifact id="imported-files" title="Git Cloned Files" type="bundled">
<codinitArtifact id="imported-files" title="Git Cloned Files" type="bundled">
${fileContents
.map(
(file) =>
`<exampleAction type="file" filePath="${file.path}">
${escapeExampleTags(file.content)}
</exampleAction>`,
`<codinitAction type="file" filePath="${file.path}">
${escapeCodinitTags(file.content)}
</codinitAction>`,
)
.join('\n')}
</exampleArtifact>`,
</codinitArtifact>`,
id: generateId(),
createdAt: new Date(),
};
Expand Down
14 changes: 7 additions & 7 deletions app/components/chat/Markdown.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { stripCodeFenceFromArtifact } from './Markdown';

describe('stripCodeFenceFromArtifact', () => {
it('should remove code fences around artifact element', () => {
const input = "```xml\n<div class='__exampleArtifact__'></div>\n```";
const expected = "\n<div class='__exampleArtifact__'></div>\n";
const input = "```xml\n<div class='__codinitArtifact__'></div>\n```";
const expected = "\n<div class='__codinitArtifact__'></div>\n";
expect(stripCodeFenceFromArtifact(input)).toBe(expected);
});

it('should handle code fence with language specification', () => {
const input = "```typescript\n<div class='__exampleArtifact__'></div>\n```";
const expected = "\n<div class='__exampleArtifact__'></div>\n";
const input = "```typescript\n<div class='__codinitArtifact__'></div>\n```";
const expected = "\n<div class='__codinitArtifact__'></div>\n";
expect(stripCodeFenceFromArtifact(input)).toBe(expected);
});

Expand All @@ -24,15 +24,15 @@ describe('stripCodeFenceFromArtifact', () => {
});

it('should handle artifact without code fences', () => {
const input = "<div class='__exampleArtifact__'></div>";
const input = "<div class='__codinitArtifact__'></div>";
expect(stripCodeFenceFromArtifact(input)).toBe(input);
});

it('should handle multiple artifacts but only remove fences around them', () => {
const input = [
'Some text',
'```typescript',
"<div class='__exampleArtifact__'></div>",
"<div class='__codinitArtifact__'></div>",
'```',
'```',
'regular code',
Expand All @@ -42,7 +42,7 @@ describe('stripCodeFenceFromArtifact', () => {
const expected = [
'Some text',
'',
"<div class='__exampleArtifact__'></div>",
"<div class='__codinitArtifact__'></div>",
'',
'```',
'regular code',
Expand Down
6 changes: 3 additions & 3 deletions app/components/chat/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const Markdown = memo(({ children, html = false, limitedMarkdown = false
const components = useMemo(() => {
return {
div: ({ className, children, node, ...props }) => {
if (className?.includes('__exampleArtifact__')) {
if (className?.includes('__codinitArtifact__')) {
const messageId = node?.properties.dataMessageId as string;

if (!messageId) {
Expand Down Expand Up @@ -97,7 +97,7 @@ export const Markdown = memo(({ children, html = false, limitedMarkdown = false
export const stripCodeFenceFromArtifact = (content: string) => {
if (
!content ||
(!content.includes('__exampleArtifact__') &&
(!content.includes('__codinitArtifact__') &&
!content.includes('__codinitThinking__') &&
!content.includes('__thinkingArtifact__'))
) {
Expand All @@ -107,7 +107,7 @@ export const stripCodeFenceFromArtifact = (content: string) => {
const lines = content.split('\n');
const artifactLineIndex = lines.findIndex(
(line) =>
line.includes('__exampleArtifact__') ||
line.includes('__codinitArtifact__') ||
line.includes('__codinitThinking__') ||
line.includes('__thinkingArtifact__'),
);
Expand Down
2 changes: 1 addition & 1 deletion app/components/chat/UserMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ export function UserMessage({ content }: UserMessageProps) {
}

function stripMetadata(content: string) {
const artifactRegex = /<exampleArtifact\s+[^>]*>[\s\S]*?<\/exampleArtifact>/gm;
const artifactRegex = /<codinitArtifact\s+[^>]*>[\s\S]*?<\/codinitArtifact>/gm;
return content.replace(MODEL_REGEX, '').replace(PROVIDER_REGEX, '').replace(artifactRegex, '');
}
12 changes: 6 additions & 6 deletions app/components/git/GitUrlImport.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { BaseChat } from '~/components/chat/BaseChat';
import { Chat } from '~/components/chat/Chat.client';
import { useGit } from '~/lib/hooks/useGit';
import { useChatHistory } from '~/lib/persistence';
import { createCommandsMessage, detectProjectCommands, escapeExampleTags } from '~/utils/projectCommands';
import { createCommandsMessage, detectProjectCommands, escapeCodinitTags } from '~/utils/projectCommands';
import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
import { ImportErrorModal } from '~/components/ui/ImportErrorModal';

Expand Down Expand Up @@ -77,16 +77,16 @@ export function GitUrlImport() {
const filesMessage: Message = {
role: 'assistant',
content: `Cloning the repo ${repoUrl} into ${workdir}
<exampleArtifact id="imported-files" title="Git Cloned Files" type="bundled">
<codinitArtifact id="imported-files" title="Git Cloned Files" type="bundled">
${fileContents
.map(
(file) =>
`<exampleAction type="file" filePath="${file.path}">
${escapeExampleTags(file.content)}
</exampleAction>`,
`<codinitAction type="file" filePath="${file.path}">
${escapeCodinitTags(file.content)}
</codinitAction>`,
)
.join('\n')}
</exampleArtifact>`,
</codinitArtifact>`,
id: generateId(),
createdAt: new Date(),
};
Expand Down
2 changes: 1 addition & 1 deletion app/components/mcp/MCPDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function MCPDialog({ isOpen, onClose, initialTab = 'integrations' }: MCPD
)}
aria-label="Close MCP settings"
>
<div className="i-heroicons:x-mark-solid w-4 h-4" />
<div className="i-lucide:x w-4 h-4" />
</button>
</RadixDialog.Close>

Expand Down
2 changes: 1 addition & 1 deletion app/components/mcp/components/MCPContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function TabContent({ tab }: { tab: TabType }) {
return (
<div className="flex items-center justify-center h-full text-codinit-elements-textSecondary">
<div className="text-center">
<div className="i-heroicons:exclamation-triangle w-12 h-12 mx-auto mb-4 opacity-50" />
<div className="i-lucide:alert-triangle w-12 h-12 mx-auto mb-4 opacity-50" />
<p className="text-sm">Tab not found</p>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/lib/.server/llm/create-summary.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { generateText, type CoreTool, type GenerateTextResult, type Message } from 'ai';
import type { IProviderSetting } from '~/types/model';
import { DEFAULT_MODEL, DEFAULT_PROVIDER, PROVIDER_LIST } from '~/utils/constants';
import { extractCurrentContext, extractPropertiesFromMessage, simplifyExampleActions } from './utils';
import { extractCurrentContext, extractPropertiesFromMessage, simplifyCodinitActions } from './utils';
import { createScopedLogger } from '~/utils/logger';
import { LLMManager } from '~/lib/modules/llm/manager';

Expand Down Expand Up @@ -29,7 +29,7 @@ export async function createSummary(props: {
} else if (message.role == 'assistant') {
let content = message.content;

content = simplifyExampleActions(content);
content = simplifyCodinitActions(content);
content = content.replace(/<div class=\\"__codinitThought__\\">.*?<\/div>/s, '');
content = content.replace(/<think>.*?<\/think>/s, '');

Expand Down
4 changes: 2 additions & 2 deletions app/lib/.server/llm/select-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
createFilesContext,
extractCurrentContext,
extractPropertiesFromMessage,
simplifyExampleActions,
simplifyCodinitActions,
} from './utils';
import { createScopedLogger } from '~/utils/logger';
import { LLMManager } from '~/lib/modules/llm/manager';
Expand Down Expand Up @@ -41,7 +41,7 @@ export async function selectContext(props: {
} else if (message.role == 'assistant') {
let content = message.content;

content = simplifyExampleActions(content);
content = simplifyCodinitActions(content);

content = content.replace(/<div class=\\"__codinitThought__\\">.*?<\/div>/s, '');
content = content.replace(/<think>.*?<\/think>/s, '');
Expand Down
36 changes: 3 additions & 33 deletions app/lib/.server/llm/stream-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { allowedHTMLElements } from '~/utils/markdown';
import { LLMManager } from '~/lib/modules/llm/manager';
import { createScopedLogger } from '~/utils/logger';
import { createFilesContext, extractPropertiesFromMessage } from './utils';
import { MCPService } from '~/lib/services/mcpService';

export type Messages = Message[];

Expand All @@ -21,8 +20,6 @@ export interface StreamingOptions extends Omit<Parameters<typeof _streamText>[0]
supabaseUrl?: string;
};
};
enableMCPTools?: boolean;
selectedMCP?: string | null;
}

const logger = createScopedLogger('stream-text');
Expand Down Expand Up @@ -69,7 +66,7 @@ export async function streamText(props: {
content = content.replace(/<codinitThinking[^>]*>.*?<\/codinitThinking>/gs, '');

content = content.replace(
/<exampleAction type="file" filePath="package-lock\.json">[\s\S]*?<\/exampleAction>/g,
/<codinitAction type="file" filePath="package-lock\.json">[\s\S]*?<\/codinitAction>/g,
'[package-lock.json content removed]',
);

Expand Down Expand Up @@ -185,22 +182,7 @@ ${lockedFilesListString}

// console.log(systemPrompt, processedMessages);

// Get MCP tools if enabled
let mcpTools = {};

if (options?.enableMCPTools) {
try {
const mcpService = MCPService.getInstance();
mcpTools = mcpService.getToolsForServer(options.selectedMCP || null);
logger.debug(
`Loaded ${Object.keys(mcpTools).length} MCP tools${options.selectedMCP ? ` for server: ${options.selectedMCP}` : ''}`,
);
} catch (error) {
logger.error('Failed to load MCP tools:', error);
}
}

const streamOptions = {
return await _streamText({
model: provider.getModelInstance({
model: modelDetails.name,
serverEnv,
Expand All @@ -211,17 +193,5 @@ ${lockedFilesListString}
maxTokens: dynamicMaxTokens,
messages: convertToCoreMessages(processedMessages as any),
...options,
};

// Add MCP tools if available and enabled
if (options?.enableMCPTools && Object.keys(mcpTools).length > 0) {
streamOptions.tools = mcpTools;

// Don't override toolChoice if it's already set in options
if (!streamOptions.toolChoice) {
streamOptions.toolChoice = 'auto';
}
}

return await _streamText(streamOptions);
});
}
10 changes: 5 additions & 5 deletions app/lib/.server/llm/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ export function extractPropertiesFromMessage(message: Omit<Message, 'id'>): {
return { model, provider, content: cleanedContent };
}

export function simplifyExampleActions(input: string): string {
// Using regex to match exampleAction tags that have type="file"
const regex = /(<exampleAction[^>]*type="file"[^>]*>)([\s\S]*?)(<\/exampleAction>)/g;
export function simplifyCodinitActions(input: string): string {
// Using regex to match codinitAction tags that have type="file"
const regex = /(<codinitAction[^>]*type="file"[^>]*>)([\s\S]*?)(<\/codinitAction>)/g;

// Replace each matching occurrence
return input.replace(regex, (_0, openingTag, _2, closingTag) => {
Expand Down Expand Up @@ -82,10 +82,10 @@ export function createFilesContext(files: FileMap, useRelativePath?: boolean) {
filePath = path.replace('/home/project/', '');
}

return `<exampleAction type="file" filePath="${filePath}">${codeWithLinesNumbers}</exampleAction>`;
return `<codinitAction type="file" filePath="${filePath}">${codeWithLinesNumbers}</codinitAction>`;
});

return `<exampleArtifact id="code-content" title="Code Content" >\n${fileContexts.join('\n')}\n</exampleArtifact>`;
return `<codinitArtifact id="code-content" title="Code Content" >\n${fileContexts.join('\n')}\n</codinitArtifact>`;
}

export function extractCurrentContext(messages: Message[]) {
Expand Down
Loading