Rebrand to TerKix, add PWA shell & offline cache, tighten Gemini server and storage handling#4
Conversation
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? |
📝 WalkthroughWalkthroughPR này thực hiện rebranding toàn bộ dự án từ "RKix" sang "TerKix", thêm hỗ trợ PWA (Service Worker, manifest, install prompt), externalize cấu hình server (PORT, GEMINI_MODEL) vào biến môi trường, tạo storage abstraction layer, và cập nhật UI/styling toàn cầu để phù hợp với thương hiệu mới. ChangesTerKix Rebranding và PWA Enablement
Poem
🎯 3 (Moderate) | ⏱️ ~20 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)
✨ Simplify code
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.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/App.tsx (1)
2014-2020:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftKhông mở preview ngoài bằng
document.write()cùng origin.
indexHtmlCodelà nội dung workspace có thể đến từ prompt/Gemini. Nhánh này ghi nó vàoabout:blankdo chính app mở ra, nên script trong preview sẽ chạy cùng origin với ứng dụng và có thể đọclocalStorage, gọi API same-origin, hoặc thao tácwindow.opener. Inline preview phía dưới đã được sandbox; nút này đang bỏ qua toàn bộ lớp cách ly đó.Muốn giữ “Open External”, hãy mở một route/static page chỉ chứa
<iframe sandbox>rồi truyềnsrcDoc/message vào iframe, hoặc vô hiệu hóa external preview cho nội dung không tin cậy.🤖 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 `@src/App.tsx` around lines 2014 - 2020, The current onClick handler uses window.open + document.write to render indexHtmlCode which executes with the app's origin; change this to avoid document.write: either route the "Open External" action to a dedicated static page/route (e.g. /external-preview) that renders a single <iframe sandbox> and communicates the HTML via postMessage or sets iframe.srcdoc, or disable/grey-out the button when indexHtmlCode is untrusted. Update the onClick logic (the handler that calls window.open, document.write and uses indexHtmlCode) to open the safe preview route or trigger the sandboxed iframe flow instead of writing directly into the new window.
🤖 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 `@index.html`:
- Line 11: The apple-touch-icon currently points to an SVG
(href="/terkix-logo.svg"), which iOS Safari ignores; replace or add a PNG touch
icon and update the webmanifest icons to include PNG fallbacks: change the link
rel="apple-touch-icon" href to a generated PNG (or add an additional <link
rel="apple-touch-icon" href="/terkix-logo.png" sizes="180x180"> alongside the
SVG), and in manifest.webmanifest ensure the icons array contains PNG entries
(e.g., 192x192/512x512 PNG) so iOS Home Screen and other platforms will load the
proper PNG icons.
In `@public/sw.js`:
- Around line 18-39: The fetch handler is doing a blanket cache-first for all
same-origin GETs which causes stale API responses and navigation/shortcut
mismatches and caches error responses; update the fetch event listener to
branch: for navigations (event.request.mode === "navigate") use a network-first
strategy that falls back to the precached navigation entry (e.g., '/' or your
precached index.html) so shortcuts like "/?section=files" can resolve offline;
for API or dynamic endpoints (e.g., requestUrl.pathname.startsWith("/api/") or
other dynamic prefixes) use network-first and only cache when response.ok is
true (status 200) to avoid caching 404/500; for other static assets you can keep
cache-first via caches.match; keep references to event.respondWith,
caches.match, CACHE_NAME, cache.put and ensure you only call cache.put with
response.clone() after verifying response.ok.
In `@server.ts`:
- Line 35: The PORT constant is parsed but not validated, allowing invalid
values like "abc", negative numbers or >65535 to reach server.listen; update the
logic that defines PORT to validate Number.parseInt(process.env.PORT || "3000",
10) by checking for NaN and ensuring an integer in the valid port range
(0–65535) and fall back to 3000 when invalid; locate the constant named PORT and
replace its assignment with a guarded parse + range check (use Number.isInteger
and range checks) so server.listen always receives a safe port number.
- Around line 91-93: The POST handler for app.post("/api/gemini/command") is
unprotected and can be abused; add server-side authentication and throttling:
implement middleware (e.g., auth middleware that checks a configured server API
key or JWT in the Authorization header) and a simple rate-limiter middleware
that wraps the route, then apply them to the route handling the
GeminiCommandRequest payload; ensure the handler validates the key and returns
401/429 on failure and logs unauthorized/rate-limited attempts before calling
the existing Gemini invocation logic.
In `@src/App.tsx`:
- Around line 167-169: The initial pwaInstallState should not default to "ready"
unconditionally; change its initialization to detect if the app is already
running in standalone and set pwaInstallState to "installed" when appropriate
(use a lazy useState initializer that checks typeof window !== "undefined" and
evaluates window.matchMedia('(display-mode: standalone)').matches ||
(window.navigator as any).standalone), and keep existing listeners that update
installPromptEvent and call setPwaInstallState on 'beforeinstallprompt' and
'appinstalled' so the UI reflects the real installed state; update references to
pwaInstallState, setPwaInstallState, installPromptEvent, and
setInstallPromptEvent accordingly.
- Around line 123-127: The current validator passed into readJsonStorage for the
"terkix_projects" key only checks id and files, but the UI reads many other
Project fields; update the predicate used in the useState initializer (the arrow
passed to readJsonStorage in the projects state) to validate the full Project
surface used by the renderer (at minimum: id, name, description, deployments,
activeBranch, commitHistory, files and the expected types for each
files/commit/deployment item), ensuring nested arrays/objects have the required
properties and types so malformed/legacy records are rejected and
PRESET_PROJECTS used instead.
- Around line 134-140: currentSection is always initialized to "terminal" and
never reads the URL, so the PWA shortcut ?section=... is ignored; update the
initialization of currentSection (the useState holding currentSection and
setCurrentSection) to parse window.location.search (via URLSearchParams) for a
"section" value and use that as the initial state (falling back to "terminal" if
absent/invalid), or add a useEffect that reads URLSearchParams on mount and
calls setCurrentSection accordingly; reference the currentSection state and
setCurrentSection symbols when implementing this change.
In `@src/utils/storage.ts`:
- Line 6: The check function isBrowserStorageAvailable can throw when access to
window.localStorage is blocked; wrap its body in a try/catch so it safely
returns false on any exception. Update the isBrowserStorageAvailable
implementation to first verify typeof window !== "undefined" and then try
reading/using window.localStorage inside a try block, returning true if
accessible and false from the catch (ensuring callers like the useState lazy
initializer don't crash the app).
- Around line 60-61: Hàm readStringStorage đang dùng `|| fallback`, khiến giá
trị chuỗi rỗng ("") bị coi là falsy và bị thay bằng fallback; thay bằng phép
kiểm tra nullish (hoặc kiểm tra === undefined) để chỉ dùng fallback khi
getStoredValue(key, legacyKeys) là null hoặc undefined. Cụ thể, trong khối try
nơi gọi getStoredValue(key, legacyKeys), thay logic `... || fallback` bằng `...
?? fallback` (hoặc `const v = getStoredValue(...); return v === undefined ?
fallback : v;`) để đảm bảo chuỗi rỗng được trả nguyên vẹn.
---
Outside diff comments:
In `@src/App.tsx`:
- Around line 2014-2020: The current onClick handler uses window.open +
document.write to render indexHtmlCode which executes with the app's origin;
change this to avoid document.write: either route the "Open External" action to
a dedicated static page/route (e.g. /external-preview) that renders a single
<iframe sandbox> and communicates the HTML via postMessage or sets
iframe.srcdoc, or disable/grey-out the button when indexHtmlCode is untrusted.
Update the onClick logic (the handler that calls window.open, document.write and
uses indexHtmlCode) to open the safe preview route or trigger the sandboxed
iframe flow instead of writing directly into the new window.
🪄 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: fbace136-edf4-46cb-93e8-4f2ebc06d631
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/terkix-logo.svgis excluded by!**/*.svg
📒 Files selected for processing (18)
.env.exampleREADME.mdindex.htmlmetadata.jsonpackage.jsonpublic/manifest.webmanifestpublic/sw.jsserver.tssrc/App.tsxsrc/components/ContactsManager.tsxsrc/components/DashboardOverview.tsxsrc/components/PluginManager.tsxsrc/components/TelemetryD3Chart.tsxsrc/data/presets.tssrc/index.csssrc/main.tsxsrc/utils/storage.tsvite.config.ts
There was a problem hiding this comment.
5 issues found across 20 files
You’re at about 96% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01a608d453
ℹ️ 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".
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Signed-off-by: Huỳnh Thương <252359928+Huynhthuongg@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d3f8a142b5
ℹ️ 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".
|
Meticulous was unable to execute a test run for this PR because the most recent commit is associated with multiple PRs. To execute a test run, please try pushing up a new commit that is only associated with this PR. Last updated for commit |
Motivation
Description
dotenvconfig, health endpoint (/api/health),GEMINI_MODELenv support, lazyGoogleGenAIinit, request/response helpers (normalizeFiles,parseGeminiJson), stronger JSON schema and error handling for/api/gemini/command, and safer port parsing.public/manifest.webmanifest,public/sw.js, andpublic/terkix-logo.svg, expanded index meta tags, and many UI refinements and Vietnamese/localized labels.src/utils/storage.ts(read/write helpers with legacy-key migration), replaced directlocalStorageusage inApp.tsxwith these helpers, addedmain.tsxservice worker registration, updated CSS for new visual styles, and added README and updated.env.example.package.json(name,version, scripts and dependencies ordering) and broughtpackage-lock.jsoninto sync with the changes.Testing
npm run typecheckand it completed successfully.npm run buildand the build succeeded without errors.Codex Task
Summary by cubic
Rebranded the app to TerKix and shipped an installable PWA with offline shell caching, hardened the Gemini server, and moved to safer client storage. Added persistent terminal command history and an online/offline status for smoother use on flaky networks.
New Features
public/manifest.webmanifest,public/sw.js, service worker registration; offline-first shell caching.GEMINI_MODELand safePORTparsing, lazyGoogleGenAIinit, typed/api/gemini/commandpayloads with stricter validation, and/api/health.src/utils/storage.tswith validators and legacy-key migration; replaced directlocalStorage.metadata.jsonupdates including microphone permission.Refactors
terkix-terminal-osv1.0.5, addedpreview/typecheck; refreshed.env.example,package-lock.json, and README.Written for commit d3f8a14. Summary will update on new commits.