Dashboard UI refresh, editor/workspace refactor, Docker executor and external-import tooling#4
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
📝 WalkthroughSummary by CodeRabbitCập Nhật Phiên Bản
WalkthroughPR tái cấu trúc kiến trúc editor với routing động, bổ sung cơ chế import repository bên ngoài, và cập nhật các dịch vụ thực thi code qua Docker/JavaScript/Python. Đồng thời chuẩn hóa quote style và cấu hình toàn bộ codebase. ChangesEditor Architecture Refactoring
External Repository Integration
Execution Services Refactoring
Configuration and Style Normalization
🎯 4 (Complex) | ⏱️ ~60 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
✨ Simplify code
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed due to a network error. Warning Review ran into problems🔥 ProblemsLinked repositories: Your configuration references 1 linked repositories, but your current plan allows 0. Analyzed ``, skipped Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Kilo Code Review could not run — your account is out of credits. Add credits or switch to a free model to enable reviews on this change. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1726433246
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
server/services/pythonExecutor.ts (1)
23-23:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTên file tạm ở Line 23 có thể va chạm khi nhiều request cùng mili-giây.
terkix_${Date.now()}.pykhông đảm bảo duy nhất trong tải đồng thời, có thể dẫn tới ghi đè chéo giữa 2 phiên chạy.Đề xuất tạo tên file tạm duy nhất
+import { randomUUID } from "crypto"; ... - const tempFile = path.join(tempDir, `terkix_${Date.now()}.py`); + const tempFile = path.join(tempDir, `terkix_${randomUUID()}.py`);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/services/pythonExecutor.ts` at line 23, The temp file naming using `terkix_${Date.now()}.py` in the `tempFile` assignment can collide under concurrent requests; change the generation to a truly unique filename (e.g., use a UUID or a random suffix and/or include `process.pid` or use `fs.mkdtemp`) when building `path.join(tempDir, ...)` so each invocation of the function that creates `tempFile` yields a unique path and prevents cross-request overwrites; update the `tempFile` creation site accordingly (replace reliance on `Date.now()` with a secure unique id generator such as `crypto.randomUUID()` or similar).server/controllers/executeController.ts (1)
8-8:⚠️ Potential issue | 🔴 Critical | ⚡ Quick win
useDockerđang bị client điều khiển và mặc định rơi vào local execution.Ở Line 8,
useDocker = falselấy từ request body. Với luồng client hiện tại (hooks/useExecutor.ts:13-34) không gửiuseDocker, nên mặc định luôn chạy nhánh local ở Line 31-37; đồng thời attacker cũng có thể épuseDocker=falseđể bypass sandbox.Đề xuất khóa quyết định sandbox ở phía server
- const { code, language, projectId, useDocker = false } = req.body; + const { code, language, projectId } = req.body; + const useDocker = process.env.EXECUTION_MODE !== "local";Also applies to: 19-37
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/controllers/executeController.ts` at line 8, The controller currently trusts client-supplied useDocker from req.body (const { code, language, projectId, useDocker = false }), allowing clients to force local execution; remove useDocker from the client destructure and instead decide sandboxing server-side (e.g., compute a server-only flag like const useDocker = determineExecutionMode(projectId, req.user) or enforce const useDocker = true/DEFAULT_DOCKER), update executeController.ts where the execution branch uses useDocker (the local vs docker decision around the lines handling local execution), and add/consume a server-side helper (determineExecutionMode or isSandboxedExecution) so attacker-controlled requests cannot bypass the sandbox.server/services/jsExecutor.ts (1)
14-23:⚠️ Potential issue | 🔴 CriticalTimeout không chặn được vòng lặp vô hạn khi JS executor chạy đồng bộ trên main thread
setTimeout(lines 14-23) chỉ được xử lý nếu event loop còn chạy; nhưng đoạn thực thi tạo hàm bằngnew Function(...)rồi gọiexecuteCode(mockConsole)(lines 50-53) chạy đồng bộ, nên code nhưwhile(true){}sẽ khóa event loop và callback timeout không kịp hoạt động.server/services/jsExecutor.tskhông có cơ chế isolation/cưỡng chế dừng (không thấyworker_threads/Worker/child_process.fork/vm).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/services/jsExecutor.ts` around lines 14 - 23, The current timeout implemented with setTimeout cannot stop synchronous infinite loops because execution happens on the main thread; refactor so code execution runs inside a separate isolate (e.g., a worker thread or child process) instead of calling new Function(...) synchronously in executeCode/whatever method that currently invokes executeCode(mockConsole); spawn a Worker (worker_threads) or fork a child_process, send the source to that worker, start a timer in the parent that calls worker.terminate()/child.kill() on timeout, and handle success/error messages back to the parent (clear the timeout on normal completion). Ensure you replace the direct synchronous call site (the code that creates new Function and calls executeCode) with IPC to the worker and wire up duration, output, error, and success fields accordingly.components/ide/Terminal.tsx (1)
20-30:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winMảng
outputđược tạo lại mỗi lần render, gây chạy useEffect không cần thiết.Biến
outputđược định nghĩa là constant array bên trong component body (dòng 20-23), nên nó được tạo lại với reference mới mỗi lần component render. useEffect ở dòng 26-30 phụ thuộc vàooutput, dẫn đến việc effect chạy sau mỗi lần render thay vì chỉ khi nội dung output thay đổi.🔧 Đề xuất sửa: di chuyển `output` ra ngoài component
+const getTerminalOutput = (projectId: string) => [ + "$ Welcome to Terkix Builder Terminal", + `$ Attached to project ${projectId}`, +]; + export default function Terminal({ projectId, isOpen = true, onClose, height = "200px", }: TerminalProps) { const terminalRef = useRef<HTMLDivElement>(null); - const output = [ - "$ Welcome to Terkix Builder Terminal", - `$ Attached to project ${projectId}`, - ]; + const output = useMemo(() => getTerminalOutput(projectId), [projectId]); const [isMaximized, setIsMaximized] = useState(false);Hoặc đơn giản hơn, nếu chỉ cần scroll một lần khi mount:
const terminalRef = useRef<HTMLDivElement>(null); const output = [ "$ Welcome to Terkix Builder Terminal", `$ Attached to project ${projectId}`, ]; const [isMaximized, setIsMaximized] = useState(false); useEffect(() => { if (terminalRef.current) { terminalRef.current.scrollTop = terminalRef.current.scrollHeight; } - }, [output]); + }, [projectId]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/ide/Terminal.tsx` around lines 20 - 30, The local constant output is recreated on every render, causing the useEffect that scrolls terminalRef (useEffect referencing output) to run unnecessarily; fix by making output stable—either move the output array declaration out of the component or memoize it with useMemo (e.g., const output = useMemo(() => [...], [projectId]) ) and then keep the useEffect dependency on output (or if you only need to scroll on mount, change the effect to an empty dependency array and run once). Ensure you update references to output and keep terminalRef.scrollTop logic inside the same useEffect that now depends on the stable output.components/ide/EditorWorkspace.tsx (1)
15-32:⚠️ Potential issue | 🟠 Major | ⚡ Quick winState editor đang bị dùng chung giữa các project, dễ chạy nhầm mã theo
projectIdcũ.
useEditorStoređang giữcode/languageở scope global; khi đổi project, workspace mới vẫn có thể dùng state của project trước. Điều này làm lệch dữ liệu thực thi theoprojectId.Đề xuất chỉnh nhanh
-import { useState } from "react"; +import { useEffect, useState } from "react"; @@ export default function EditorWorkspace({ projectId }: EditorWorkspaceProps) { - const { code, language } = useEditorStore(); + const { code, language, reset } = useEditorStore(); @@ + useEffect(() => { + reset(); + }, [projectId, reset]); + const { execute, isExecuting } = useExecutor();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/ide/EditorWorkspace.tsx` around lines 15 - 32, The editor state (code/language) is global via useEditorStore causing cross-project leakage; update EditorWorkspace to use project-scoped editor state by making useEditorStore accept projectId (or provide a project-specific selector) and read/write code and language for that project only, then ensure handleSave and handleRun use those project-scoped values when calling execute(code, language, projectId); change any set/update calls in the store to key by projectId (e.g., getEditorState(projectId)/setEditorState(projectId,...)) so each project has isolated code/language state.components/editors/CodeMirrorEditor.tsx (1)
31-69:⚠️ Potential issue | 🟠 MajorTránh recreate
EditorViewkhicodeprop đổi (giữ ổn định cursor/undo)Hiện tại
useEffecttạoEditorState/new EditorView(...)đang phụ thuộc[code, language, onChange, readOnly, theme], và cleanupview.destroy(). Vì vậy mỗi khicodethay đổi (thường là theo từng lần gõ nếu parent set state từonChange) sẽ destroy/recreate editor → tốn tài nguyên và dễ gây giật UI/mất trạng thái (cursor/undo).Đề xuất tách lifecycle init và sync nội dung
export default function CodeMirrorEditorComponent({ @@ }: CodeMirrorEditorProps) { const editorRef = useRef<HTMLDivElement>(null); + const viewRef = useRef<EditorView | null>(null); useEffect(() => { if (!editorRef.current) return undefined; @@ - const view = new EditorView({ + viewRef.current = new EditorView({ state, parent: editorRef.current, }); return () => { - view.destroy(); + viewRef.current?.destroy(); + viewRef.current = null; }; - }, [code, language, onChange, readOnly, theme]); + }, [language, onChange, readOnly, theme]); + + useEffect(() => { + const view = viewRef.current; + if (!view) return; + const current = view.state.doc.toString(); + if (current !== code) { + view.dispatch({ + changes: { from: 0, to: current.length, insert: code }, + }); + } + }, [code]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/editors/CodeMirrorEditor.tsx` around lines 31 - 69, Initialize the EditorView only once instead of recreating it on every code prop change: move the EditorState.create / new EditorView(...) call into an effect that runs on mount (using editorRef and creating the view, and calling view.destroy() on unmount), and separate a second effect that watches the code prop and updates the editor content via the existing EditorView instance (use view.dispatch to apply a document replacement only when the current view state doc differs from the incoming code). Keep other extensions (getLanguageExtension(), theme handling, EditorView.updateListener.of, EditorView.editable.of) attached on init and avoid reattaching the update listener on every code change so cursor/undo state is preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/`(dashboard)/page.tsx:
- Around line 110-116: The "Open editor" Link is hardcoded to "/editor/1";
update it to use a dynamic project ID instead (either the first project's id or
route to create a new project) so it matches how projects are rendered elsewhere
(e.g., the project list using project.id). Locate the Link in
app/(dashboard)/page.tsx (the "Open editor" button) and replace the static href
with a computed value: if projects array exists and has at least one item use
`/editor/${projects[0].id}` (or equivalent firstProject.id), otherwise use the
new-project route (or a create project fallback); ensure the variable you use
(projects or firstProject) is available in the component scope.
In `@components/ide/Terminal.tsx`:
- Around line 20-23: The Terminal component currently initializes a hardcoded
const output array (lines with "$ Welcome..." and `$ Attached to project
${projectId}`) so it never shows dynamic logs; change this to accept an output
prop (e.g. output?: string[] or outputText?: string) or use internal state
(useState<string[]>) named output and expose a setter/append method so execution
results can be wired in, update places referencing output and projectId
accordingly, and add a TODO comment in Terminal to indicate where the
execute/logging stream should push new lines (or prop should be provided) so the
terminal becomes dynamic.
In `@docs/terkix-repository-imports.md`:
- Around line 19-36: Add a short system-requirements note to the docs near the
npm run import:terkix-repos examples stating that git must be installed and
available on the PATH (e.g., “Requires git installed and accessible via PATH”),
so users running npm run import:terkix-repos (and its flags --dry-run and
--update-only) get a clear error cause if git is missing.
In `@integrations/terkix-repositories.json`:
- Around line 1-42: Add a fail-fast JSON schema/field validation in
scripts/import-terkix-repositories.mjs before iterating manifest.repositories:
verify manifest is an object and manifest.repositories is a non-empty array and
manifest.defaultDirectory is a non-empty string, then for each repository ensure
required fields id, name, url, localPath, and purpose exist and are strings
(reject empty values). If validation fails, throw or processLogger.error and
exit with a clear message describing which repository index/id and which field
is missing/invalid so the import loop never attempts git operations with
undefined values.
In `@next.config.js`:
- Around line 56-57: The rewrite is hard-coded to
"http://localhost:3001/api/:path*"—update the rewrites() destination to use the
NEXT_PUBLIC_API_URL env var instead: read NEXT_PUBLIC_API_URL from process.env
(or from the exported env object) and build the destination as
`${NEXT_PUBLIC_API_URL}/api/:path*` so rewrites() proxies to the configured API
host in staging/production rather than localhost; target the rewrites() entry
that currently maps source: "/api/:path*" and destination:
"http://localhost:3001/api/:path*".
In `@package.json`:
- Around line 13-16: The package.json currently has both "lint" and "typecheck"
set to "tsc --noEmit" while eslint remains in devDependencies; update scripts
and related configs to remove duplication and align tooling: either (A) restore
"lint" to run ESLint (e.g., "eslint . --ext .ts,.tsx") and keep "typecheck" as
"tsc --noEmit", ensure CI workflows call npm run lint, and keep eslint
devDependency and config, or (B) make "lint" a typecheck alias (remove eslint
from devDependencies and delete/disable ESLint config and any CI lint job/docs
referencing it). Also search CI workflows (".github/workflows") and docs to
update or remove npm run lint references accordingly and clean up remaining
eslint config files if you choose option B.
In `@scripts/import-terkix-repositories.mjs`:
- Line 10: Dòng tạo manifest bằng const manifest =
JSON.parse(readFileSync(manifestPath, "utf8")); thiếu xử lý lỗi; bọc cuộc gọi
readFileSync/JSON.parse trong try/catch (xung quanh biểu thức tạo manifest), khi
lỗi xảy ra gọi console.error hoặc processLogger.error mô tả rõ manifestPath và
lỗi, và kết thúc script với process.exit(1); tham chiếu tới manifest,
manifestPath, readFileSync và JSON.parse để xác định vị trí sửa.
- Around line 42-75: The loop over manifest.repositories uses
repository.localPath and repository.url without validating repository shape, so
add schema/field checks before using them: implement a small validator (e.g.,
validateRepository or isValidRepository) that ensures repository is an object
and has required string fields localPath and url (and optionally name), call it
before resolving paths in the loop, log and push a failure or skip the entry
when validation fails (include repository index or JSON.stringify(repository) in
the log), and avoid accessing repository.localPath/repository.url when
validation fails; update any places referencing manifest.repositories to use the
validated/filtered list or guard branches accordingly.
- Around line 42-75: Validate and sanitize repository.localPath before using it:
after computing localPath with resolve(rootDir, repository.localPath) (and
gitDir via resolve(localPath, ".git")), ensure the resolved localPath is a child
of rootDir (e.g., compare
path.normalize(localPath).startsWith(path.normalize(rootDir) + path.sep)) and
reject or record a failure if it is outside rootDir or an absolute/traversal
path; also handle and log invalid paths early in the loop (the same place where
run, existsSync, updateOnly, failures, and console messages are used) so
cloning/pulling never operates on unexpected filesystem locations.
In `@server/services/dockerExecutor.ts`:
- Around line 81-94: The code accumulates unbounded stdout/stderr into strings
(stdout, stderr) via child.stdout.on and child.stderr.on which can OOM; fix by
introducing a max buffer size constant (e.g., MAX_CAPTURE_BYTES) and in the
child.stdout.on/child.stderr.on handlers only append until that limit (e.g.,
keep last N bytes or stop appending and set a truncated flag), and once the
limit is hit remove or no-op the corresponding listener to stop growth; update
any downstream uses of stdout/stderr to account for possible truncation and keep
existing timeoutId/child.kill behavior intact.
- Around line 48-59: The container invocation currently only sets
--memory/--cpus in the args array and leaves network/capabilities/pids and
stdout/stderr unbounded; update the args (the array named "args" in
server/services/dockerExecutor.ts) to harden the container by adding flags such
as --network=none, --pids-limit=<small>, --cap-drop=ALL,
--security-opt=no-new-privileges, --read-only and appropriate tmpfs/volume flags
(or minimal --cap-add if a specific capability is required) to reduce attack
surface, and then limit runtime resources as needed; also modify the
stdout/stderr handling logic (the streaming/buffering code around lines handling
output in server/services/dockerExecutor.ts) to enforce a maximum aggregated
output size (implement a byte counter that stops/terminates the container once a
threshold is exceeded or truncates additional output) and stream output
incrementally rather than buffering unboundedly to prevent DoS/OOM.
In `@server/services/pythonExecutor.ts`:
- Around line 45-59: The timeout handler currently calls process.kill() and
resolve() immediately (using timeoutId and process.kill()), causing possible
double-resolve and duplicate cleanup because
process.on("close")/process.on("error") also resolve and unlink the tempFile;
change the lifecycle so the timeout handler only marks the process as timed out,
calls process.kill(), and waits for the existing process.on("close") handler to
perform the single resolve/cleanup (or use a single shared "settled"
flag/cleanup function checked by all handlers to ensure exactly one
resolve/unlink and to clear the timeoutId). Also make temp file names truly
unique by replacing the Date.now()-based name with a UUID or other random id
(e.g., crypto.randomUUID()) when creating tempFile so concurrent requests won't
collide. Ensure timeoutId is cleared in the close/error paths and that unlink is
only executed once.
---
Outside diff comments:
In `@components/editors/CodeMirrorEditor.tsx`:
- Around line 31-69: Initialize the EditorView only once instead of recreating
it on every code prop change: move the EditorState.create / new EditorView(...)
call into an effect that runs on mount (using editorRef and creating the view,
and calling view.destroy() on unmount), and separate a second effect that
watches the code prop and updates the editor content via the existing EditorView
instance (use view.dispatch to apply a document replacement only when the
current view state doc differs from the incoming code). Keep other extensions
(getLanguageExtension(), theme handling, EditorView.updateListener.of,
EditorView.editable.of) attached on init and avoid reattaching the update
listener on every code change so cursor/undo state is preserved.
In `@components/ide/EditorWorkspace.tsx`:
- Around line 15-32: The editor state (code/language) is global via
useEditorStore causing cross-project leakage; update EditorWorkspace to use
project-scoped editor state by making useEditorStore accept projectId (or
provide a project-specific selector) and read/write code and language for that
project only, then ensure handleSave and handleRun use those project-scoped
values when calling execute(code, language, projectId); change any set/update
calls in the store to key by projectId (e.g.,
getEditorState(projectId)/setEditorState(projectId,...)) so each project has
isolated code/language state.
In `@components/ide/Terminal.tsx`:
- Around line 20-30: The local constant output is recreated on every render,
causing the useEffect that scrolls terminalRef (useEffect referencing output) to
run unnecessarily; fix by making output stable—either move the output array
declaration out of the component or memoize it with useMemo (e.g., const output
= useMemo(() => [...], [projectId]) ) and then keep the useEffect dependency on
output (or if you only need to scroll on mount, change the effect to an empty
dependency array and run once). Ensure you update references to output and keep
terminalRef.scrollTop logic inside the same useEffect that now depends on the
stable output.
In `@server/controllers/executeController.ts`:
- Line 8: The controller currently trusts client-supplied useDocker from
req.body (const { code, language, projectId, useDocker = false }), allowing
clients to force local execution; remove useDocker from the client destructure
and instead decide sandboxing server-side (e.g., compute a server-only flag like
const useDocker = determineExecutionMode(projectId, req.user) or enforce const
useDocker = true/DEFAULT_DOCKER), update executeController.ts where the
execution branch uses useDocker (the local vs docker decision around the lines
handling local execution), and add/consume a server-side helper
(determineExecutionMode or isSandboxedExecution) so attacker-controlled requests
cannot bypass the sandbox.
In `@server/services/jsExecutor.ts`:
- Around line 14-23: The current timeout implemented with setTimeout cannot stop
synchronous infinite loops because execution happens on the main thread;
refactor so code execution runs inside a separate isolate (e.g., a worker thread
or child process) instead of calling new Function(...) synchronously in
executeCode/whatever method that currently invokes executeCode(mockConsole);
spawn a Worker (worker_threads) or fork a child_process, send the source to that
worker, start a timer in the parent that calls worker.terminate()/child.kill()
on timeout, and handle success/error messages back to the parent (clear the
timeout on normal completion). Ensure you replace the direct synchronous call
site (the code that creates new Function and calls executeCode) with IPC to the
worker and wire up duration, output, error, and success fields accordingly.
In `@server/services/pythonExecutor.ts`:
- Line 23: The temp file naming using `terkix_${Date.now()}.py` in the
`tempFile` assignment can collide under concurrent requests; change the
generation to a truly unique filename (e.g., use a UUID or a random suffix
and/or include `process.pid` or use `fs.mkdtemp`) when building
`path.join(tempDir, ...)` so each invocation of the function that creates
`tempFile` yields a unique path and prevents cross-request overwrites; update
the `tempFile` creation site accordingly (replace reliance on `Date.now()` with
a secure unique id generator such as `crypto.randomUUID()` or similar).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 00ff0388-822d-4544-b641-74c6c3116257
📒 Files selected for processing (27)
.gitignoreREADME.mdapp/(dashboard)/page.tsxapp/editor/[projectId]/page.tsxapp/layout.tsxcomponents/editors/CodeMirrorEditor.tsxcomponents/editors/MonacoEditor.tsxcomponents/ide/EditorPanel.tsxcomponents/ide/EditorWorkspace.tsxcomponents/ide/FileExplorer.tsxcomponents/ide/Navbar.tsxcomponents/ide/Preview.tsxcomponents/ide/Terminal.tsxdocs/terkix-repository-imports.mdexternal/.gitkeepintegrations/terkix-repositories.jsonnext.config.jspackage.jsonpostcss.config.jsscripts/import-terkix-repositories.mjsserver/controllers/executeController.tsserver/middleware/errorHandler.tsserver/services/dockerExecutor.tsserver/services/jsExecutor.tsserver/services/pythonExecutor.tstailwind.config.jstsconfig.json
Motivation
external/workspace without committing their sources.Description
app/(dashboard)/page.tsx) with refreshed layout, status/stats cards, AndroidX checklist, and polished project cards.app/editor/[projectId]/page.tsxand reusablecomponents/ide/EditorWorkspace.tsx, and updated IDE components includingEditorPanel,FileExplorer,Navbar,Terminal,Preview, and editor adapters (MonacoEditor,CodeMirrorEditor).server/services/dockerExecutor.tsnow uses thedockerCLI viachild_process.spawnwith resource limits and label cleanup;jsExecutorandpythonExecutorwere hardened for timeouts, safer output handling, and clearer error reporting;server/controllers/executeController.tsandserver/middleware/errorHandler.tscontain small fixes/formatting updates.integrations/terkix-repositories.json,scripts/import-terkix-repositories.mjs,docs/terkix-repository-imports.md, and an ignoredexternal/workspace (external/.gitkeep) with.gitignoreupdated to excludeexternal/*but keep.gitkeep.package.jsonscripts (typecheck,import:terkix-repos),next.config.jsadjustments for headers/rewrites/images and server externals,tsconfig.jsonpath/style cleanups, addedpostcss.config.js, and updatedtailwind.config.jsandREADME.mdto document the new import workflow.Testing
npm run typecheck(maps totsc --noEmit) and the checks completed successfully.npm run import:terkix-repos -- --dry-runto verify generated git/clone commands and the manifest parsing, which completed without errors.Codex Task
Summary by cubic
Refreshes the dashboard UI and adds a dedicated editor route, while hardening code execution with a CLI-based Docker runner. Introduces an
external/import workflow to clone Terkix/RKIX repos locally without vendoring them.New Features
app/editor/[projectId]usingEditorWorkspacefor a cleaner IDE URL.integrations/terkix-repositories.json, scriptnpm run import:terkix-repos, ignoredexternal/workspace, and docs.Refactors
dockerCLI with memory/CPU limits and 10s timeout; label-based cleanup; safer JS/Python executors with timeouts and clearer errors.next.config.jsheaders/rewrites/image patterns, PostCSS (tailwindcss,autoprefixer),tsconfig.jsonpath/style cleanup,package.jsonscripts (typecheck,import:terkix-repos), and.gitignoreforexternal/*.Written for commit 1726433. Summary will update on new commits.