Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion apps/browser-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"devDependencies": {
"@babel/generator": "^7.28.0",
"@babel/parser": "^7.28.0",
"@babel/traverse": "^7.27.0",
"@babel/traverse": "^7.28.0",
"@babel/types": "^7.28.1",
"@crxjs/vite-plugin": "2.0.0-beta.30",
"@tailwindcss/vite": "^4.1.11",
Expand Down
17 changes: 9 additions & 8 deletions apps/browser-extension/src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { executeCode } from '@evaluate/engine/execute';
import { searchRuntimes } from '@evaluate/engine/runtimes';
import {
getRuntimeDefaultFileName,
searchRuntimes,
} from '@evaluate/engine/runtimes';
import type { ExecuteResult, PartialRuntime } from '@evaluate/shapes';
import type { ProtocolWithReturn } from 'webext-bridge';
import { onMessage, sendMessage } from 'webext-bridge/background';
Expand Down Expand Up @@ -67,21 +70,19 @@ browser.contextMenus.onClicked.addListener(async (info, tab) => {

const promises = [];
for (const runtime of runtimes) {
const fileName = getRuntimeDefaultFileName(runtime.id) ?? 'file.code';
const initialPromise = executeCode({
runtime: runtime.id,
// TODO: Use the get runtime default file name function
files: { 'file.code': code },
entry: 'file.code',
files: { [fileName]: code },
entry: fileName,
})
.then((result) => {
posthog?.capture('executed_code', {
runtime_id: runtime.id,
code_length: code.length,
code_lines: code.split('\n').length,
compile_successful: result.compile ? result.compile.code === 0 : null,
execution_successful:
result.run.code === 0 &&
(!result.compile || result.compile.code === 0),
compile_successful: result.compile?.success ?? null,
execution_successful: result.success,
});
return result;
})
Expand Down
38 changes: 20 additions & 18 deletions apps/browser-extension/src/content-script/execution/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,27 @@ export function ExecutionDialog({
</DialogHeader>

<DialogContent>
<Tabs defaultValue={runtimes[~successIndex ? successIndex : 0]?.id}>
<TabsList className="w-full">
{runtimes.map((runtime) => (
<TabsTrigger key={runtime.id} value={runtime.id}>
{runtime.name}
</TabsTrigger>
))}
</TabsList>
{results.length > 0 && (
<Tabs defaultValue={runtimes[~successIndex ? successIndex : 0]?.id}>
<TabsList className="w-full">
{runtimes.map((runtime) => (
<TabsTrigger key={runtime.id} value={runtime.id}>
{runtime.name}
</TabsTrigger>
))}
</TabsList>

{runtimes.map((runtime, i) => (
<TabsContent key={runtime.id} value={runtime.id}>
<ResultDialog
code={code}
runtime={runtime}
result={results[i]!}
/>
</TabsContent>
))}
</Tabs>
{runtimes.map((runtime, i) => (
<TabsContent key={runtime.id} value={runtime.id}>
<ResultDialog
code={code}
runtime={runtime}
result={results[i]!}
/>
</TabsContent>
))}
</Tabs>
)}
</DialogContent>
</DialogBody>
</Dialog>
Expand Down
21 changes: 11 additions & 10 deletions apps/browser-extension/src/content-script/execution/result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Label } from '@evaluate/components/label';
import { Textarea } from '@evaluate/components/textarea';
import type { ExecuteResult, PartialRuntime } from '@evaluate/shapes';
import { ExternalLinkIcon } from 'lucide-react';
import { useMemo } from 'react';
import { twMerge as cn } from 'tailwind-merge';
import { makeEditCodeUrl, makePickRuntimeUrl } from '~/helpers/make-url';

Expand All @@ -16,11 +15,13 @@ export function ResultDialog({
runtime: PartialRuntime;
result: ExecuteResult;
}) {
const display = useMemo(() => {
if (!result) return { code: undefined, output: undefined };
if (result.compile?.code) return result.compile;
return result.run;
}, [result]);
let output = result.output;
if (result.compile?.expired)
output =
'Your code compilation exceeded the allotted time and was terminated. Consider optimising your code for faster compilation.';
else if (result.run.expired)
output =
'Your code execution exceeded the allotted time and was terminated. Consider optimising it for better performance.';

return (
<div className="space-y-2">
Expand All @@ -29,12 +30,12 @@ export function ResultDialog({
<Textarea
readOnly
name="output"
value={display.output}
placeholder="The code ran successfully, but it didn't produce an output to the console."
value={output}
placeholder="Your code executed successfully; however, it did not generate any output for the console."
className={cn(
'min-h-[40vh] w-full resize-none border-2',
display.code && 'border-destructive',
display.output && 'font-mono',
!result.success && 'border-destructive',
result.output && 'font-mono',
)}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/discord-bot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@
"zod": "4.0.5"
},
"devDependencies": {
"tsup": "^8.4.0"
"tsup": "^8.5.0"
}
}
8 changes: 4 additions & 4 deletions apps/discord-bot/src/components/evaluate-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ class ArgumentsInput extends TextInput {
customId = 'args';
label = 'Arguments';
placeholder = 'Additional command line arguments to pass to the program.';
style = TextInputStyle.Paragraph;
minLength = 1;
style = TextInputStyle.Short;
minLength = 0;
maxLength = 500;
required = false;
}
Expand All @@ -82,8 +82,8 @@ class InputInput extends TextInput {
customId = 'input';
label = 'Input';
placeholder = 'The STDIN input to provide to the program.';
style = TextInputStyle.Paragraph;
minLength = 1;
style = TextInputStyle.Short;
minLength = 0;
maxLength = 500;
required = false;
}
90 changes: 27 additions & 63 deletions apps/discord-bot/src/handlers/evaluate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ import {
Row,
type User,
} from '@buape/carbon';
import { compress } from '@evaluate/engine/compress';
import { executeCode } from '@evaluate/engine/execute';
import {
getRuntimeDefaultFileName,
searchRuntimes,
} from '@evaluate/engine/runtimes';
import type { ExecuteResult, PartialRuntime } from '@evaluate/shapes';
import { EditEvaluationButton } from '~/components/edit-evaluation-button';
import { OpenEvaluationButton } from '~/components/open-evaluation-button';
import env from '~/env';
import { captureEvent } from '~/services/posthog';
import { codeBlock } from '~/utilities/discord-formatting';
import { getInteractionContext } from '~/utilities/session-context';
import { EditEvaluationButton } from '~/components/edit-evaluation-button.js';
import { OpenEvaluationButton } from '~/components/open-evaluation-button.js';
import { captureEvent } from '~/services/posthog.js';
import { codeBlock } from '~/utilities/discord-formatting.js';
import { makeEditCodeUrl } from '~/utilities/make-url.js';
import { getInteractionContext } from '~/utilities/session-context.js';

function isNew(
interaction: CommandInteraction | ModalInteraction,
Expand All @@ -42,30 +41,11 @@ function isEdit(
);
}

function compressOptions(options: {
runtime: PartialRuntime;
code: string;
args?: string;
input?: string;
}) {
const identifier =
typeof options.runtime === 'string' ? options.runtime : options.runtime.id;
const fileName = getRuntimeDefaultFileName(identifier) ?? 'file.code';
return compress({
files: {
[fileName]: options.code,
'::input::': options.input,
'::args::': options.args,
},
entry: fileName,
focused: fileName,
});
}

export async function handleEvaluating(
interaction: CommandInteraction | ModalInteraction,
options: { runtime: string; code: string; args?: string; input?: string },
) {
// HACK: If trying to edit an existing evaluation owned by another user, create new instead
if (
interaction.rawData.message &&
interaction.rawData.message.interaction_metadata?.user.id !==
Expand Down Expand Up @@ -93,9 +73,10 @@ export async function handleEvaluating(
throw new Error(message);
}

const fileName = getRuntimeDefaultFileName(runtime.id) ?? 'file.code';
const executeOptions = {
files: { 'file.code': options.code },
entry: 'file.code',
files: { [fileName]: options.code },
entry: fileName,
input: options.input,
args: options.args,
};
Expand All @@ -116,37 +97,23 @@ export async function handleEvaluating(
runtime_id: runtime.id,
code_length: options.code.length,
code_lines: options.code.split('\n').length,
compile_successful: result.compile ? result.compile.code === 0 : null,
execution_successful:
result.run.code === 0 && (!result.compile || result.compile.code === 0),
compile_successful: result.compile?.success ?? null,
execution_successful: result.success,
});

const resultKey = result?.compile?.code ? 'compile' : 'run';
const hasTimedOut = result[resultKey]?.signal === 'SIGKILL';
const doesHaveDisplayableOutput = result[resultKey]?.output?.trim() !== '';

let output = result[resultKey]!.output;
if (!doesHaveDisplayableOutput) {
// TODO: This stuff would be better handled by the executeCode function
const isRun = resultKey === 'run';
if (hasTimedOut) {
if (isRun)
output =
'Your code execution exceeded the allotted time and was terminated. Consider optimising it for better performance.';
else
output =
'Your code compilation exceeded the allotted time and was terminated. Consider optimising your code for faster compilation.';
} else {
output =
'Your code executed successfully; however, it did not generate any output for the console.';
}
} else if (output.length > 1000) {
output = `Output was too large to display, [click here to view the full output](${
env.WEBSITE_URL
}/playgrounds/${runtime.id}#${compressOptions({ ...options, runtime })}).`;
} else {
output = codeBlock(output, 1000);
}
let output = result.output;
if (result.compile?.expired)
output =
'Your code compilation exceeded the allotted time and was terminated. Consider optimising your code for faster compilation.';
else if (result.run.expired)
output =
'Your code execution exceeded the allotted time and was terminated. Consider optimising it for better performance.';
else if (!output)
output =
'Your code executed successfully; however, it did not generate any output for the console.';
else if (output.length > 900)
output = `Output was too large to display, [click here to view the full output](${makeEditCodeUrl(options)})`;
else output = codeBlock(output, 1000);

return interaction.reply(
createEvaluationPayload(
Expand All @@ -172,10 +139,7 @@ export function createEvaluationPayload(
const embed = new Embed({
title: 'Code Evaluation',
description: `**${options.runtime.name}**\n${codeBlock(options.runtime.aliases[0]!, options.code, 4000)}`,
color:
result.run.code === 0 && (!result.compile || result.compile.code === 0)
? 0x2fc086
: 0xff0000,
color: result.success ? 0x2fc086 : 0xff0000,
fields: [],
author: user
? { name: user.username!, icon_url: user.avatarUrl! }
Expand Down Expand Up @@ -205,7 +169,7 @@ export function createEvaluationPayload(
new Row([
new EditEvaluationButton(),
new OpenEvaluationButton(
`${env.WEBSITE_URL}playgrounds/${options.runtime.id}#${compressOptions(options)}`,
makeEditCodeUrl({ ...options, runtime: options.runtime.id }),
),
]),
],
Expand Down
41 changes: 41 additions & 0 deletions apps/discord-bot/src/utilities/make-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// TODO: Move with apps/browser-extension/src/helpers/make-url.ts to shared package

import { compress } from '@evaluate/engine/compress';
import { getRuntimeDefaultFileName } from '@evaluate/engine/runtimes';
import env from '~/env';

export function makeEditCodeUrl(options: {
runtime: string;
code: string;
args?: string;
input?: string;
}) {
const fileName = getRuntimeDefaultFileName(options.runtime) ?? 'file.code';
const state = compress({
files: {
[fileName]: options.code,
'::args::': options.args,
'::input::': options.input,
},
entry: fileName,
focused: fileName,
});
return `${env.WEBSITE_URL}playgrounds/${options.runtime}#${state}`;
}

export function makePickRuntimeUrl(options: {
code: string;
args?: string;
input?: string;
}) {
const state = compress({
files: {
'file.code': options.code,
'::args::': options.args,
'::input::': options.input,
},
entry: 'file.code',
focused: 'file.code',
});
return `${env.WEBSITE_URL}playgrounds#${state}`;
}
4 changes: 2 additions & 2 deletions apps/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"jszip": "^3.10.1",
"lucide-react": "^0.525.0",
"material-icon-theme": "^5.24.0",
"next": "^15.3.5",
"next": "15.3.5",
"next-themes": "npm:@wits/next-themes@^0.2.16",
"posthog-js": "^1.257.0",
"react": "^19.1.0",
Expand All @@ -55,7 +55,7 @@
},
"devDependencies": {
"@million/lint": "^1.0.14",
"@next/bundle-analyzer": "^15.4.1",
"@next/bundle-analyzer": "15.3.5",
"@tailwindcss/postcss": "^4.1.11",
"@types/file-saver": "^2.0.7",
"@types/react": "^19.1.8",
Expand Down
Loading