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
16 changes: 15 additions & 1 deletion install_prerequisite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,20 @@ else
rm -rf evcxr-v0.17.0-x86_64-unknown-linux-gnu
fi


#install rappel, nasm and set all the required dependencies
if [ -e "/usr/local/bin/rappel" ]; then
echo "File /usr/local/bin/rappel exists."
else
echo "File /usr/local/bin/rappel does not exist. installing..."
apt-get install -y --no-install-recommends libedit-dev
apt-get install -y --no-install-recommends nasm
git clone https://github.com/yrp604/rappel.git
cd rappel
make
ln -s $GOTTY_DIR/rappel/bin/rappel /usr/local/bin/rappel
chmod 755 /usr/local/bin/rappel
cd ..
fi

#install gointerpreter
git clone https://github.com/vickeykumar/Go-interpreter.git
Expand Down Expand Up @@ -236,6 +249,7 @@ if [ $run_tests -eq 1 ]; then
"sqlite3 --version"
"tsc --version"
"ts-node --version"
"echo "nop" | rappel"
)


Expand Down
3 changes: 2 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ bindata:
bindata/static: bindata
mkdir bindata/static

bindata/static/index.html: bindata/static resources/index.html resources/profile.html resources/robots.txt jsconsole/build/static/jsconsole.html
bindata/static/index.html: bindata/static resources/index.html resources/profile.html resources/practice.html resources/robots.txt jsconsole/build/static/jsconsole.html
cp resources/index.html bindata/static/index.html
cp resources/profile.html bindata/static/profile.html
cp resources/practice.html bindata/static/practice.html
cp resources/robots.txt bindata/static/robots.txt
cp jsconsole/build/static/jsconsole.html bindata/static/jsconsole.html

Expand Down
1 change: 1 addition & 0 deletions src/containers/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var Commands2memLimitMap = map[string]int64{
"evcxr": 50, // rust REPL
"sqlite3": 10,
"ts-node": 50,
"rappel": 2,
}

var memLimitMutex sync.Mutex
Expand Down
134 changes: 127 additions & 7 deletions src/resources/chat-widget/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,29 @@ const WIDGET_MESSAGES_HISTORY_CONTAINER_ID =
const WIDGET_THINKING_BUBBLE_ID = "chat-widget__thinking_bubble";
const CHAT_LIST_KEY = "chat-list"

const interviewPrompt = `
You are an expert coding interviewer conducting a technical interview. Your goal is to assess the candidate's ability to solve a coding problem independently.

### Interview Process:
1. Start by presenting the problem statement and constraints clearly from IDE.
2. Do NOT give the solution or direct hints unless the user explicitly asks for help or is stuck.
3. Encourage the candidate to **think aloud** and explain their approach.
4. If the candidate provides an incorrect approach, ask **clarifying questions** to guide them.
5. Only give small hints when necessary, helping them think in the right direction without revealing the full solution.
6. Use Socratic questioning to probe their understanding:
- "What data structure might be useful for this problem?"
- "Can you optimize your current approach?"
- "What are the edge cases you need to consider?"
7. If the candidate asks for a full solution, politely **decline** and encourage them to try again.
8. If they are truly stuck (e.g., multiple failed attempts), provide a **small hint** to unblock them.
9. Once they reach a correct approach, let them implement it and provide constructive feedback.

### Response Guidelines:
- Be professional and supportive but **not too helpful**.
- Encourage the user to debug their code rather than fixing it for them.
- Give feedback in a way that promotes learning and problem-solving skills.
`

function generateFiveCharUUID(): string {
// Generate a UUID and extract the first 5 characters
const uuid: string = crypto.randomUUID();
Expand Down Expand Up @@ -108,17 +131,24 @@ const MAX_HISTORY_SIZE = 20;
// Initialize the conversationHistory array
let conversationHistory: MessageType[] = [];

function getcurrentIDECode(): MessageType {
let idecodemsg = {
role: "system",
content: `Openrepl IDE/Editor real-time Code Content user is working on,
(refer this code whenever user ask to debug editor/ide
code without providing any code in message): `+ fetchEditorContent(),
}
return idecodemsg;
}

// Function to add a message to the conversation history
function addMessageToHistory(role: string, content: string, uid: string=UID): void {
if (role=="user") {
// to handle multiple peer users
content = `[${role}-${uid}] ` + content;
if (conversationHistory.length >= NUM_MANDATORY_ENTRIES) {
// update editors content to msg history everytime user writes/sends message
conversationHistory[NUM_MANDATORY_ENTRIES-1] = {
role: "system",
content: "Openrepl IDE/Editor Code Content: "+ fetchEditorContent(),
}
conversationHistory[NUM_MANDATORY_ENTRIES-1] = getcurrentIDECode();
}
}

Expand Down Expand Up @@ -225,8 +255,16 @@ async function init() {
);
open({ target } as Event);
}
addMessageToHistory("system", "welcome to openrepl.com!! I am Genie. your OpenRepl AI assistant.");
addMessageToHistory("system", "documentation: "+documentation);

let welcomeprompt = "welcome to openrepl.com!! you are Genie. An OpenRepl AI";
// only four permanent prompts
if (window.location.pathname.includes("practice")) {
addMessageToHistory("system", welcomeprompt+" Interviewer.");
addMessageToHistory("system", interviewPrompt);
} else {
addMessageToHistory("system", welcomeprompt+" Assistant.");
addMessageToHistory("system", "documentation: "+documentation);
}
addMessageToHistory("system", "keywords: "+ keywords);
addMessageToHistory("system", "Openrepl IDE/EditorCodeContent: "+ fetchEditorContent());
setupFBListener();
Expand Down Expand Up @@ -256,6 +294,87 @@ const trap = createFocusTrap(containerElement, {
allowOutsideClick: true,
});

function makeResizable(containerElement: HTMLElement, target: HTMLElement) {
// Create a resizer div
const resizer = document.createElement("div");
resizer.innerHTML = `
<svg width="20" height="20" viewBox="0 0 20 20">
<line x1="4" y1="16" x2="16" y2="4" stroke="gray" stroke-width="2" />
<line x1="8" y1="16" x2="16" y2="8" stroke="gray" stroke-width="2" />
</svg>
`;
resizer.style.position = "absolute";
resizer.style.left = "5px";
resizer.style.top = "5px";
resizer.style.cursor = "nwse-resize";
resizer.style.opacity = "0.7";
resizer.style.transition = "opacity 0.2s";
resizer.style.display = "flex";
resizer.style.alignItems = "center";
resizer.style.justifyContent = "center";
resizer.style.width = "15px";
resizer.style.height = "15px";

// Style the container for a modern feel
Object.assign(containerElement.style, {
position: "absolute",
borderRadius: "10px",
boxShadow: "0 4px 10px rgba(0, 0, 0, 0.2)",
overflow: "hidden",
resize: "none", // Disable native resize
transition: "width 0.2s ease, height 0.2s ease",
});

containerElement.appendChild(resizer);

let isResizing = false;

resizer.addEventListener("mousedown", (e) => {
e.preventDefault();
isResizing = true;

const startX = e.clientX;
const startY = e.clientY;
const startWidth = containerElement.offsetWidth;
const startHeight = containerElement.offsetHeight;

function resize(e: MouseEvent) {
if (!isResizing) return;
const newWidth = Math.max(150, startWidth + (startX - e.clientX)); // Min width: 150px
const newHeight = Math.max(100, startHeight + (startY - e.clientY)); // Min height: 100px
containerElement.style.width = `${newWidth}px`;
containerElement.style.height = `${newHeight}px`;

// Recompute floating position to keep alignment
updatePosition();
}

function stopResize() {
isResizing = false;
document.removeEventListener("mousemove", resize);
document.removeEventListener("mouseup", stopResize);
}

document.addEventListener("mousemove", resize);
document.addEventListener("mouseup", stopResize);
});

function updatePosition() {
computePosition(target, containerElement, {
placement: "top-start",
middleware: [flip(), shift({ crossAxis: true, padding: 8 })],
strategy: "fixed",
}).then(({ x, y }) => {
Object.assign(containerElement.style, {
left: `${x}px`,
top: `${y}px`,
});
});
}

return updatePosition; // Return the function so it can be used if needed
}

function open(e: Event) {
if (config.closeOnOutsideClick) {
document.body.appendChild(optionalBackdrop);
Expand Down Expand Up @@ -293,6 +412,7 @@ function open(e: Event) {
});
});

makeResizable(containerElement, target);
trap.activate();

if (config.closeOnOutsideClick) {
Expand Down Expand Up @@ -486,7 +606,7 @@ async function submit(e: Event) {
const data = {
...config.user,
model: config.model,
messages: conversationHistory,
messages: [...conversationHistory, getcurrentIDECode()],
temperature: config.temperature,
max_tokens: config.max_tokens,
stream: config.responseIsAStream,
Expand Down
2 changes: 1 addition & 1 deletion src/resources/chat-widget/src/widget.css
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
width: 100%;
height: 100%;
background-image: url('images/genie-large.png'); /* Path to your animated GIF */
background-size: cover; /* Make the background cover the entire container */
background-size: contain; /* Make the background contained */
background-position: center; /* Center the background image */
background-repeat: no-repeat; /* Prevent the background image from repeating */
opacity: 0.5; /* Adjust opacity as needed */
Expand Down
35 changes: 34 additions & 1 deletion src/resources/css/scribbler-global.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
--terminal-bg-color: black;
--gutter-rotate: 90deg; /* Initial rotation angle */
--gutter-right: 3px;
--modal-duration: 1s;
--clear-color: #ebebec;
--shadow-color: rgba(0, 0, 0, 0.3);
--overlay-color: rgba(0, 0, 0, 0.6);
}

/* normalized */
Expand Down Expand Up @@ -506,4 +510,33 @@ input[type=text],[type=email], select, textarea, email {
.rev-accent-background {
background: var(--rev-accent-color);
}
/* them classes ends */
/* them classes ends */

/* loaders */
.loader, #loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 11;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #64CEAA;
width: 80px;
height: 80px;
-webkit-animation: spin 1s linear infinite;
animation: spin 1s linear infinite;
}

@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* loader ends */
27 changes: 0 additions & 27 deletions src/resources/css/scribbler-landing.css
Original file line number Diff line number Diff line change
Expand Up @@ -771,33 +771,6 @@ h2 {
padding-right:10px;
}

#loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 11;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #64CEAA;
width: 80px;
height: 80px;
-webkit-animation: spin 1s linear infinite;
animation: spin 1s linear infinite;
}

@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

/* tooltip */

.tooltip {
Expand Down
Loading
Loading