feat: Add dependency-free CodegenRestDashboard (REST commands + UI + CF webhook)#206
feat: Add dependency-free CodegenRestDashboard (REST commands + UI + CF webhook)#206codegen-sh[bot] wants to merge 4 commits intodevelopfrom
Conversation
…ds, local proxy UI, CF webhook, auto-refresh watchers, templates + follow-up automation - CodegenRestDashboard/.env.example and .gitignore for secrets - Node commands: create/resume/list/get/generate_setup_commands - Vanilla JS dashboard: header active count + hover list, pinned runs, run dialog with streaming logs, filters, model dropdown, templates tab - Local http server proxy to inject Authorization; no token in browser - Cloudflare Worker webhook handler at /webhook - Offline/mock mode for local testing without network Co-authored-by: Zeeeepa <zeeeepa@gmail.com>
…n; compact cards; notifications; new CLI (ban/unban/logs) - Persist watched + chain selections in localStorage - Inline chain editor for active runs (list + pinned) - Run dialog gains template selector and template-driven resume - Follow-up manager executes chained templates sequentially per completion - Compact UI styling and status dots - Add ban_agent_run.js, unban_agent_run.js, get_agent_run_logs.js; update index - README updates Co-authored-by: Zeeeepa <zeeeepa@gmail.com>
|
Update: Implemented full chaining and UI refinements
Files to review first:
Let me know if you’d like me to:
|
…ional CF forward; watcher consumes events for faster updates - server.js: POST /webhook stores events in-memory; GET /api/events returns+clears - webhook_server.js: forward to WEBHOOK_FORWARD_URL if set - watcher.js: poll /api/events and refresh affected runs immediately Co-authored-by: Zeeeepa <zeeeepa@gmail.com>
|
Enhancement: webhook integration + event-aware watcher and compact chain progress
This keeps the zero-dependency promise and keeps tokens server-side while improving responsiveness. If you want I can add a small “progress x/y” badge on cards next to the status dot. |
|
Marked this PR ready for review ✅ Summary
If you want any final polish (e.g., per‑card chain progress badge, even denser list, or webhook-only fast-path mode), I can add those in a small follow‑up. |
There was a problem hiding this comment.
9 issues found across 32 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="CodegenRestDashboard/dashboard/services/watcher.js">
<violation number="1" location="CodegenRestDashboard/dashboard/services/watcher.js:24">
P2: The webhook events poll runs inside the per-run loop, causing N duplicate `/api/events` requests each tick and skipping webhook processing entirely when there are no watched/pinned runs. Move the webhook polling block outside the `for (const id ...)` loop so it executes once per tick.</violation>
</file>
<file name="CodegenRestDashboard/server.js">
<violation number="1" location="CodegenRestDashboard/server.js:50">
P2: Static assets will always be blocked because `file` retains a leading `/`, causing `path.join` to ignore the dashboard directory and fail the `startsWith` check. This makes the UI unusable.</violation>
</file>
<file name="CodegenRestDashboard/dashboard/state/store.js">
<violation number="1" location="CodegenRestDashboard/dashboard/state/store.js:24">
P1: Missing closing brace for init() causes a syntax error and prevents the dashboard store from loading.</violation>
</file>
<file name="CodegenRestDashboard/utils/apiClient.js">
<violation number="1" location="CodegenRestDashboard/utils/apiClient.js:19">
P2: nodeFetch hardcodes https.request and ignores the URL protocol/port, so http:// or custom-port API_BASE values will fail. Select the request module based on u.protocol and pass u.port.</violation>
</file>
<file name="CodegenRestDashboard/dashboard/components/runDialog.js">
<violation number="1" location="CodegenRestDashboard/dashboard/components/runDialog.js:9">
P2: Interpolating `id` into `innerHTML` can lead to XSS if the run id ever contains HTML. Set the run title via `textContent` (or create the element) instead of injecting it into HTML.</violation>
<violation number="2" location="CodegenRestDashboard/dashboard/components/runDialog.js:43">
P2: Template selector initialization is inside the Resume click handler, so the dropdown and “Set Default” button are not wired up when the dialog opens. Move the selector population and apply handler outside the Resume onclick so the template UI works immediately.</violation>
</file>
<file name="CodegenRestDashboard/.env.example">
<violation number="1" location="CodegenRestDashboard/.env.example:3">
P2: Replace the hard-coded organization ID with a placeholder so users don’t accidentally use or leak a real org identifier.</violation>
</file>
<file name="CodegenRestDashboard/dashboard/components/runList.js">
<violation number="1" location="CodegenRestDashboard/dashboard/components/runList.js:44">
P2: The create-run handler reports success and clears the prompt even if `CGApi.createAgentRun` fails. Wrap the call in a try/catch so success is only shown on a successful response and errors surface to the user.</violation>
</file>
<file name="CodegenRestDashboard/webhook_server.js">
<violation number="1" location="CodegenRestDashboard/webhook_server.js:27">
P2: Signature validation uses a non‑constant‑time string comparison (`sig !== expected`), which can leak timing information. Use `crypto.subtle.verify` (or another constant‑time compare) on the raw bytes instead.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| function open(id){ | ||
| const wrapper = document.createElement('div'); | ||
| wrapper.className = 'dialog'; | ||
| wrapper.innerHTML = `<div class="panel"> |
There was a problem hiding this comment.
P2: Interpolating id into innerHTML can lead to XSS if the run id ever contains HTML. Set the run title via textContent (or create the element) instead of injecting it into HTML.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CodegenRestDashboard/dashboard/components/runDialog.js, line 9:
<comment>Interpolating `id` into `innerHTML` can lead to XSS if the run id ever contains HTML. Set the run title via `textContent` (or create the element) instead of injecting it into HTML.</comment>
<file context>
@@ -0,0 +1,91 @@
+ function open(id){
+ const wrapper = document.createElement('div');
+ wrapper.className = 'dialog';
+ wrapper.innerHTML = `<div class="panel">
+ <div class="dialog-header">
+ <div>Run #${id}</div>
</file context>
| @@ -0,0 +1,11 @@ | |||
| # Copy to .env and fill your values. Do NOT commit the .env file. | |||
| CODEGEN_API_BASE=https://api.codegen.com | |||
| CODEGEN_ORG_ID=323 | |||
There was a problem hiding this comment.
P2: Replace the hard-coded organization ID with a placeholder so users don’t accidentally use or leak a real org identifier.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CodegenRestDashboard/.env.example, line 3:
<comment>Replace the hard-coded organization ID with a placeholder so users don’t accidentally use or leak a real org identifier.</comment>
<file context>
@@ -0,0 +1,11 @@
+# Copy to .env and fill your values. Do NOT commit the .env file.
+CODEGEN_API_BASE=https://api.codegen.com
+CODEGEN_ORG_ID=323
+CODEGEN_TOKEN=sk-REPLACE_ME
+# Optional: run in mock/offline mode (server serves fixtures; no network calls)
</file context>
| const body = { prompt: prompt.value, model: model.value }; | ||
| if (!body.prompt) { CGToast.toast('Prompt required'); return; } | ||
| if (repo.value) body.repo_id = Number(repo.value); | ||
| await CGApi.createAgentRun(body); |
There was a problem hiding this comment.
P2: The create-run handler reports success and clears the prompt even if CGApi.createAgentRun fails. Wrap the call in a try/catch so success is only shown on a successful response and errors surface to the user.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CodegenRestDashboard/dashboard/components/runList.js, line 44:
<comment>The create-run handler reports success and clears the prompt even if `CGApi.createAgentRun` fails. Wrap the call in a try/catch so success is only shown on a successful response and errors surface to the user.</comment>
<file context>
@@ -0,0 +1,104 @@
+ const body = { prompt: prompt.value, model: model.value };
+ if (!body.prompt) { CGToast.toast('Prompt required'); return; }
+ if (repo.value) body.repo_id = Number(repo.value);
+ await CGApi.createAgentRun(body);
+ CGToast.toast('Agent run created');
+ // No manual refresh button: watcher will auto-refresh the list shortly
</file context>
| ); | ||
| const mac = await crypto.subtle.sign('HMAC', key, encoder.encode(bodyText)); | ||
| const expected = [...new Uint8Array(mac)].map(b => b.toString(16).padStart(2,'0')).join(''); | ||
| if (!sig || sig !== expected) { |
There was a problem hiding this comment.
P2: Signature validation uses a non‑constant‑time string comparison (sig !== expected), which can leak timing information. Use crypto.subtle.verify (or another constant‑time compare) on the raw bytes instead.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CodegenRestDashboard/webhook_server.js, line 27:
<comment>Signature validation uses a non‑constant‑time string comparison (`sig !== expected`), which can leak timing information. Use `crypto.subtle.verify` (or another constant‑time compare) on the raw bytes instead.</comment>
<file context>
@@ -0,0 +1,52 @@
+ );
+ const mac = await crypto.subtle.sign('HMAC', key, encoder.encode(bodyText));
+ const expected = [...new Uint8Array(mac)].map(b => b.toString(16).padStart(2,'0')).join('');
+ if (!sig || sig !== expected) {
+ return new Response('Invalid signature', { status: 401 });
+ }
</file context>
- Fix store.js init() braces and state load - Move webhook polling outside per-run loop; clean watcher - Harden static file serving (path normalize, traversal guard) - Make API client honor http/https and custom ports - Add browser templating engine and integrate in auto follow-ups + run dialog - Populate template selector correctly; resolve variables on resume - Add Node CLI render_template for variable testing Co-authored-by: Zeeeepa <zeeeepa@gmail.com>
|
Summary of updates addressing chaining, templating, and stability: Fixes and improvements
Manual validation (offline)
Notes / Known gaps
Suggested follow‑ups
Files touched
Happy to iterate further or port changes to the other dashboard PRs after you decide which one to keep as the base. |
There was a problem hiding this comment.
2 issues found across 9 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="CodegenRestDashboard/utils/templateEngine.js">
<violation number="1" location="CodegenRestDashboard/utils/templateEngine.js:20">
P2: Referencing `module` without checking if CommonJS exports exist causes the browser build to throw immediately. Guard the assignment before accessing `module`.</violation>
</file>
<file name="CodegenRestDashboard/server.js">
<violation number="1" location="CodegenRestDashboard/server.js:55">
P1: `startsWith` does not prevent directory traversal; a request like `/../dashboard.config.json` resolves outside `dashboard/` but still passes the guard because the path string begins with the same prefix. Use `path.relative` (or append a path separator) to ensure the resolved path stays inside the static root.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| const baseDir = path.join(__dirname, 'dashboard'); | ||
| const rel = file.replace(/^\/+/, ''); | ||
| const p = path.normalize(path.join(baseDir, rel)); | ||
| if (!p.startsWith(baseDir)) { |
There was a problem hiding this comment.
P1: startsWith does not prevent directory traversal; a request like /../dashboard.config.json resolves outside dashboard/ but still passes the guard because the path string begins with the same prefix. Use path.relative (or append a path separator) to ensure the resolved path stays inside the static root.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CodegenRestDashboard/server.js, line 55:
<comment>`startsWith` does not prevent directory traversal; a request like `/../dashboard.config.json` resolves outside `dashboard/` but still passes the guard because the path string begins with the same prefix. Use `path.relative` (or append a path separator) to ensure the resolved path stays inside the static root.</comment>
<file context>
@@ -46,10 +46,13 @@ function contentType(filePath) {
+ const baseDir = path.join(__dirname, 'dashboard');
+ const rel = file.replace(/^\/+/, '');
+ const p = path.normalize(path.join(baseDir, rel));
+ if (!p.startsWith(baseDir)) {
res.writeHead(403); return res.end('Forbidden');
}
</file context>
|
|
||
| // Expose for browser and Node | ||
| if (typeof window !== 'undefined') window.CGTemplate = { renderTemplate }; | ||
| module.exports = { renderTemplate }; |
There was a problem hiding this comment.
P2: Referencing module without checking if CommonJS exports exist causes the browser build to throw immediately. Guard the assignment before accessing module.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CodegenRestDashboard/utils/templateEngine.js, line 20:
<comment>Referencing `module` without checking if CommonJS exports exist causes the browser build to throw immediately. Guard the assignment before accessing `module`.</comment>
<file context>
@@ -0,0 +1,22 @@
+
+ // Expose for browser and Node
+ if (typeof window !== 'undefined') window.CGTemplate = { renderTemplate };
+ module.exports = { renderTemplate };
+})();
+
</file context>
Summary
What’s included
How to run locally
Notes
Validation
Follow-ups (optional)
💻 View my work • 👤 Initiated by @Zeeeepa • About Codegen
⛔ Remove Codegen from PR • 🚫 Ban action checks