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
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,10 @@ export interface ExistingFunction {
// ==================================
export interface Attachment {
name: string;
path?: string
path?: string;
content?: string;
status: AttachmentStatus;
mimeType?: string;
}

export enum AttachmentStatus {
Expand Down Expand Up @@ -291,6 +292,7 @@ export interface ChatEntry {
export interface FileAttatchment {
fileName: string;
content: string;
mimeType?: string;
}

export type CodeContext =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ When generating Ballerina code strictly follow these syntax and structure guidel
- For GraphQL service related queries, if the user hasn't specified their own GraphQL Schema, write the proposed GraphQL schema for the user query right after the explanation before generating the Ballerina code. Use the same names as the GraphQL Schema when defining record types.
- Some libaries has instructions field in their API documentation. Follow those instructions strictly when using those libraries.
- You should only generate tests if the user explicitly asks for them in the query. You must use the 'ballerina/test' and whatever services associated when writing tests. Respect the instructions field in ballerina/test library and testGenerationInstruction field in whatever library associated with the service in the library API documentation when writing tests.
- For workflow-based requirements involving long-running processes, state management, or orchestration of multiple steps, use the 'ballerina/workflow' module.

${getLanglibInstructions()}

Expand Down Expand Up @@ -179,12 +180,12 @@ ${getLanglibInstructions()}

# File modifications
- You must apply changes to the existing source code using the provided ${[
FILE_BATCH_EDIT_TOOL_NAME,
FILE_SINGLE_EDIT_TOOL_NAME,
FILE_WRITE_TOOL_NAME,
].join(
", "
)} tools. The complete existing source code will be provided in the <existing_code> section of the user prompt.
FILE_BATCH_EDIT_TOOL_NAME,
FILE_SINGLE_EDIT_TOOL_NAME,
FILE_WRITE_TOOL_NAME,
].join(
", "
)} tools. The complete existing source code will be provided in the <existing_code> section of the user prompt.
- When making replacements inside an existing file, provide the **exact old string** and the **exact new string** with all newlines, spaces, and indentation, being mindful to replace nearby occurrences together to minimize the number of tool calls.
- Do NOT create a new markdown file to document each change or summarize your work unless specifically requested by the user.
- Do not manually add/modify toml files (Ballerina.toml/Dependencies.toml). For Config.toml configuration management, use ${CONFIG_COLLECTOR_TOOL}.
Expand Down Expand Up @@ -218,16 +219,25 @@ export function getUserPrompt(params: GenerateAgentCodeRequest, tempProjectPath:

// Add file attachments if available
if (params.fileAttachmentContents && params.fileAttachmentContents.length > 0) {
const attachmentsText = params.fileAttachmentContents.map((attachment) =>
`## File: ${attachment.fileName}\n\`\`\`\n${attachment.content}\n\`\`\``
).join('\n\n');

content.push({
type: 'text' as const,
text: `<User Attachments>
${attachmentsText}
</User Attachments>`
});
for (const attachment of params.fileAttachmentContents) {
if (attachment.mimeType?.startsWith('image/')) {
// Add image attachment
content.push({
type: 'image' as const,
image: attachment.content,
});
} else {
// Add text file attachment
const attachmentsText = params.fileAttachmentContents.map((attachment) =>
`## File: ${attachment.fileName}\n\`\`\`\n${attachment.content}\n\`\`\``).join('\n\n');
content.push({
type: 'text' as const,
text: `<User Attachments>
${attachmentsText}
</User Attachments>`
});
}
}
}

content.push({
Expand All @@ -246,15 +256,15 @@ ${params.usecase}
}


function getGenerationType(isPlanMode:boolean):string {
function getGenerationType(isPlanMode: boolean): string {
if (isPlanMode) {
return `<system-reminder> Plan Mode is enabled. Make sure to use task management using ${TASK_WRITE_TOOL_NAME} </system-reminder>`;
}
return `<system-reminder> Edit Mode is enabled. Avoid using Task management and make the edits directly. </system-reminder>`;
}

function getNPSuffix(projects: ProjectSource[], op?: OperationType): string {
let basePrompt:string = "Note: You are in a special Natural Programming mode. Follow the NP guidelines strictly in addition to what you've given. \n";
let basePrompt: string = "Note: You are in a special Natural Programming mode. Follow the NP guidelines strictly in addition to what you've given. \n";
if (!op) {
return "";
} else if (op === "CODE_FOR_USER_REQUIREMENT") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,7 @@ const AIChat: React.FC = () => {
const fileAttatchments = attachments.map((file) => ({
fileName: file.name,
content: file.content,
mimeType: file?.mimeType,
}));

console.log("Submitting agent prompt:", { useCase, agentMode, codeContext, operationType, fileAttatchments });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ const TEXT_BASED_TYPES = [
"",
];

/**
* Allowed image file types.
*/
const IMAGE_TYPES = [
"image/jpeg",
"image/jpg",
"image/png",
"image/gif",
"image/webp",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we validate with anthropic docs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

];

/**
* Combined text and image types for general commands.
*/
const TEXT_AND_IMAGE_TYPES = [...TEXT_BASED_TYPES, ...IMAGE_TYPES];

/**
* Allowed file types for commands expecting documents/images.
*/
Expand All @@ -62,7 +78,7 @@ export const getFileTypesForCommand = (command: Command | null): string[] => {
case Command.TypeCreator:
return DOCUMENT_TYPES;
default:
return TEXT_BASED_TYPES;
return TEXT_AND_IMAGE_TYPES;
}
};

Expand All @@ -71,7 +87,7 @@ export const getFileTypesForCommand = (command: Command | null): string[] => {
*/
export const acceptResolver = (command: Command | null): string => {
if (!command) {
return TEXT_BASED_TYPES.join(",");
return TEXT_AND_IMAGE_TYPES.join(",");
}
return getFileTypesForCommand(command).join(",");
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,30 @@ export const readFileAsText = (file: File): Promise<string> => {
reader.readAsText(file);
});
};

/**
* Helper to check if a file is an image based on MIME type.
*/
export const isImageFile = (file: File): boolean => {
return file.type.startsWith('image/');
};

/**
* Read image file as base64 data URL.
*/
export const readFileAsBase64 = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();

reader.onload = () => {
if (typeof reader.result === "string") {
resolve(reader.result);
} else {
reject(new Error("File content is not a string."));
}
};

reader.onerror = () => reject(new Error("Error reading the image file."));
reader.readAsDataURL(file);
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import { AttachmentHandler } from "./attachmentHandler";
import { Attachment, AttachmentStatus } from "@wso2/ballerina-core";
import { readFileAsText, validateFileSize, validateFileType } from "./attachmentUtils";
import { readFileAsText, readFileAsBase64, validateFileSize, validateFileType } from "./attachmentUtils";

/**
* Abstract base class that provides common file-attachment handling logic.
Expand Down Expand Up @@ -64,6 +64,7 @@ export abstract class BaseAttachment implements AttachmentHandler {
name: file.name,
content,
status: AttachmentStatus.Success,
mimeType: file.type,
});
} catch {
results.push({
Expand All @@ -79,10 +80,14 @@ export abstract class BaseAttachment implements AttachmentHandler {
}

/**
* Default method to read file content as text.
* Subclasses can override this to do something else (e.g., read as Base64).
* Default method to read file content.
* Images are read as base64, text files as plain text.
* Subclasses can override this if needed.
*/
protected readFileContent(file: File): Promise<string> {
protected async readFileContent(file: File): Promise<string> {
if (file.type.startsWith('image/')) {
return readFileAsBase64(file);
}
return readFileAsText(file);
}
}
Loading