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
2 changes: 1 addition & 1 deletion CodeGen/docker_compose/intel/cpu/xeon/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ services:
ipc: host
restart: always
codegen-xeon-ui-server:
image: ${REGISTRY:-opea}/codegen-gradio-ui:${TAG:-latest}
image: ${REGISTRY:-opea}/codegen-ui:${TAG:-latest}
container_name: codegen-xeon-ui-server
depends_on:
- codegen-xeon-backend-server
Expand Down
2 changes: 1 addition & 1 deletion CodeGen/docker_compose/intel/cpu/xeon/compose_tgi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ services:
ipc: host
restart: always
codegen-xeon-ui-server:
image: ${REGISTRY:-opea}/codegen-gradio-ui:${TAG:-latest}
image: ${REGISTRY:-opea}/codegen-ui:${TAG:-latest}
container_name: codegen-xeon-ui-server
depends_on:
- codegen-xeon-backend-server
Expand Down
12 changes: 9 additions & 3 deletions CodeGen/tests/test_compose_on_xeon.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function build_docker_images() {
popd && sleep 1s

echo "Build all the images with --no-cache, check docker_image_build.log for details..."
service_list="codegen codegen-gradio-ui llm-textgen dataprep retriever embedding"
service_list="codegen codegen-ui llm-textgen dataprep retriever embedding"

docker compose -f build.yaml build ${service_list} --no-cache > ${LOG_PATH}/docker_image_build.log

Expand Down Expand Up @@ -174,6 +174,8 @@ function validate_frontend() {
npm install && npm ci && npx playwright install --with-deps
node -v && npm -v && pip list

export no_proxy="localhost,127.0.0.1,$ip_address"

exit_status=0
npx playwright test || exit_status=$?

Expand Down Expand Up @@ -244,8 +246,12 @@ function main() {
validate_megaservice
echo "::endgroup::"

echo "::group::validate_gradio"
validate_gradio
# echo "::group::validate_gradio"
# validate_gradio
# echo "::endgroup::"

echo "::group::validate_ui"
validate_frontend
echo "::endgroup::"

stop_docker "${docker_compose_files[${i}]}"
Expand Down
226 changes: 185 additions & 41 deletions CodeGen/ui/svelte/src/lib/modules/chat/Output.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,24 @@
import bash from "svelte-highlight/languages/bash";
import sql from "svelte-highlight/languages/sql";
import { marked } from "marked";
export let label = "";
import { afterUpdate, onMount } from "svelte";

export let output = "";
export let languages = "Python";
export let lang = "Python";
export let isCode = false;
export let md_output = "";
export let segments: Segment[] = [];

let outputEl: HTMLDivElement;
let copyText = "copy";
let shouldAutoscroll = true;

type Segment = {
id: number;
type: "text" | "code";
content: string;
lang?: string;
};

const languagesTag = {
Typescript: typescript,
Expand All @@ -65,53 +77,194 @@
Lua: lua,
Bash: bash,
Sql: sql,
} as { [key: string]: any };

function copyToClipboard(text) {
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand("copy");
document.body.removeChild(textArea);
} as const;

type LangKey = keyof typeof languagesTag;

const aliasMap: Record<string, LangKey> = {
javascript: "Javascript",
js: "Javascript",
jsx: "Javascript",
typescript: "Typescript",
ts: "Typescript",
tsx: "Typescript",

python: "Python",
py: "Python",

c: "C",
"c++": "Cpp",
cpp: "Cpp",
cxx: "Cpp",
csharp: "Csharp",
"c#": "Csharp",

go: "Go",
golang: "Go",
java: "Java",
swift: "Swift",
ruby: "Ruby",
rust: "Rust",
php: "Php",
kotlin: "Kotlin",
objectivec: "Objectivec",
objc: "Objectivec",
"objective-c": "Objectivec",
perl: "Perl",
matlab: "Matlab",
r: "R",
lua: "Lua",

bash: "Bash",
sh: "Bash",
shell: "Bash",
zsh: "Bash",

sql: "Sql",
};

$: normalizedLangKey = (() => {
const raw = (lang ?? "").toString().trim();
if (!raw) return null;
const lower = raw.toLowerCase();

if (lower in aliasMap) return aliasMap[lower];

const hit = (Object.keys(languagesTag) as LangKey[]).find(
(k) => k.toLowerCase() === lower
);
return hit ?? null;
})();

$: fullText = buildFullText();

function atBottom(el: HTMLElement, threshold = 8) {
return el.scrollHeight - el.scrollTop - el.clientHeight <= threshold;
}

function handleScroll() {
if (!outputEl) return;
shouldAutoscroll = atBottom(outputEl);
}

function handelCopy() {
copyToClipboard(output);
function scrollToBottom() {
if (!outputEl) return;
requestAnimationFrame(() =>
requestAnimationFrame(() => {
if (outputEl.scrollHeight) {
outputEl.scrollTop = outputEl.scrollHeight;
}
})
);
}

onMount(() => {
scrollToBottom();
});

afterUpdate(() => {
if (shouldAutoscroll) scrollToBottom();
});
async function copyAllFromDiv() {
await navigator.clipboard.writeText(outputEl.innerText);
copyText = "copied!";
setTimeout(() => {
copyText = "copy";
}, 1000);
setTimeout(() => (copyText = "copy"), 1000);
}

function copyToClipboard(text: string) {
if (navigator?.clipboard?.writeText) {
navigator.clipboard.writeText(text);
} else {
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand("copy");
document.body.removeChild(textArea);
}
}

function normalizeToKey(raw?: string | null) {
const s = (raw ?? "").trim().toLowerCase();
if (!s) return null;
if (s in aliasMap) return aliasMap[s as keyof typeof aliasMap];
const hit = (
Object.keys(languagesTag) as (keyof typeof languagesTag)[]
).find((k) => k.toLowerCase() === s);
return hit ?? null;
}

function buildFullText(): string {
if (segments && segments.length > 0) {
return segments
.map((seg) => {
if (seg.type === "code") {
const key = normalizeToKey(seg.lang) ?? "text";
return ["```" + key.toLowerCase(), seg.content, "```"].join("\n");
}
return seg.content;
})
.join("\n\n");
}

const parts: string[] = [];
if (isCode && output) {
const key = (normalizedLangKey ?? "text").toLowerCase();
parts.push(["```" + key, output, "```"].join("\n"));
}
if (md_output) {
parts.push(md_output);
}
return parts.join("\n\n");
}
</script>

<div class="flex w-full flex-col" data-testid="code-output">
<span
class=" mb-2 flex h-[3rem] w-full items-center justify-center bg-[#5856D6] px-8 py-2 text-center text-[0.89rem] uppercase leading-tight opacity-80"
>{label}</span
>

<div
class="flex justify-end border-2 border-none border-b-gray-800 bg-[#1C1C1C] px-3 text-white"
>
<button
class="rounded border border-none py-1 text-[0.8rem] text-[#abb2bf]"
on:click={() => {
handelCopy();
}}>{copyText}</button
on:click={copyAllFromDiv}>{copyText}</button
>
</div>

<div
class="code-format-style hiddenScroll h-[22rem] divide-y overflow-auto bg-[#011627]"
class="
hiddenScroll h-[22rem] overflow-auto
bg-[#011627] p-5 text-[13px]
leading-5
"
bind:this={outputEl}
on:scroll={handleScroll}
>
{#if isCode}
<Highlight language={python} code={output} let:highlighted>
<LineNumbers {highlighted} wrapLines hideBorder />
</Highlight>
{#if segments && segments.length > 0}
{#each segments as seg (seg.id)}
{#if seg.type === "code"}
<div class="relative border-t border-[#0c2233]">
<Highlight
language={languagesTag[normalizeToKey(seg.lang) ?? "Python"]}
code={seg.content}
let:highlighted
>
<LineNumbers {highlighted} wrapLines hideBorder />
</Highlight>
</div>
{:else}
<div>{@html marked(seg.content)}</div>
{/if}
{/each}
{:else}
<div class="bg-[#282c34] text-[#abb2bf]">
{@html marked(output)}
</div>
{#if isCode && output}
<Highlight language={python} code={output} let:highlighted>
<LineNumbers {highlighted} wrapLines hideBorder />
</Highlight>
{/if}
{#if md_output}
<div class="bg-[#282c34] py-2 text-[#abb2bf]">
{@html marked(md_output)}
</div>
{/if}
{/if}
</div>
</div>
Expand All @@ -120,17 +273,8 @@
.hiddenScroll::-webkit-scrollbar {
display: none;
}

.hiddenScroll {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}

.code-format-style {
resize: none;
font-size: 16px;
border: solid rgba(128, 0, 128, 0) 4px;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.19);
transition: 0.1s linear;
}
</style>
Loading
Loading