Skip to content

fix(bundler): add missing veryfront/* modules to externals - #265

Closed
kwakayama wants to merge 2 commits into
mainfrom
fix/bundler-external-veryfront-modules
Closed

kwakayama wants to merge 2 commits into
mainfrom
fix/bundler-external-veryfront-modules

Conversation

@kwakayama

Copy link
Copy Markdown
Contributor

Problem

Production builds fail with 'Could not resolve' errors for:

  • veryfront/head
  • veryfront/router
  • veryfront/context
  • veryfront/fonts

These imports work in dev mode (resolved by dev server) but fail in production builds because they're not in the externals list.

Root Cause

VERYFRONT_CLIENT_MODULES in build-context.ts only included:

  • veryfront/agent/react
  • veryfront/components/ai
  • veryfront/primitives

The missing modules are also runtime-provided and should be externalized.

Fix

Added the missing modules to VERYFRONT_CLIENT_MODULES.

Testing

  • ✅ veryfront build now succeeds for flow-ops
  • ✅ veryfront serve works with API routes
  • ✅ Pre-commit verification passes

veryfront/head, veryfront/router, veryfront/context, and veryfront/fonts
were not marked as external in the code splitter, causing production
builds to fail with 'Could not resolve' errors.

These modules are provided by the runtime and should be externalized
like veryfront/agent/react, veryfront/components/ai, and veryfront/primitives.
Copilot AI review requested due to automatic review settings February 7, 2026 23:23

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ed67e98c99

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +18 to +21
"veryfront/head",
"veryfront/router",
"veryfront/context",
"veryfront/fonts",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid externalizing core modules for unpkg/jsdelivr CDN mode

The newly externalized entries (veryfront/head, veryfront/router, veryfront/context, veryfront/fonts) will now be left as bare imports whenever moduleResolution !== "bundled". In CDN mode with provider unpkg or jsdelivr, the import map built in src/html/utils.ts only includes platform utilities when includePlatformUtilities is true (lines 156–186), so those providers do not add entries for these modules. This means any app that imports these core modules while using the unpkg/jsdelivr CDN provider will now fail at runtime with unresolved module specifiers, whereas previously they were bundled. Either gate these externals by provider or add the missing mappings for unpkg/jsdelivr to avoid breaking that configuration.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses production build failures by ensuring certain runtime-provided veryfront/* client modules are treated as externals during bundling, aligning production behavior with dev resolution.

Changes:

  • Add missing veryfront/head, veryfront/router, veryfront/context, and veryfront/fonts to the bundler externals list.
  • Bump package version in deno.json.
  • Commit dev-ui manifest updates and several runtime log dumps (appear unrelated to the PR’s stated purpose).

Reviewed changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/build/bundler/code-splitter/build-context.ts Extends VERYFRONT_CLIENT_MODULES so production builds externalize additional runtime-provided modules.
src/server/dev-ui/manifest.json Updates embedded dev-ui source strings (appears unrelated to externals fix).
deno.json Version bump from 0.1.7-rc.48 to 0.1.7-rc.49.
logs-20260207-171708.txt Added runtime logs (should not be committed).
logs-20260206-225100.txt Added runtime logs (should not be committed).
logs-20260205-182422.txt Added runtime logs (should not be committed).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread logs-20260207-171708.txt
Comment on lines +1 to +13
{"timestamp":"2026-02-07T16:16:46.319Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"309172bb-9bab-437a-83a3-cbe6382eb142","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1199}}
{"timestamp":"2026-02-07T16:16:45.268Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:44.502Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"c72ac1f1-db0d-45c1-8836-95b0414a7ac7","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1409}}
{"timestamp":"2026-02-07T16:16:43.259Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:22.343Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"24f19fe4-8c63-4c0e-9c70-313ea7a5309c","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1076}}
{"timestamp":"2026-02-07T16:16:21.434Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:10.023Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"8b2e7524-cc49-40c3-be2f-156b50de61fb","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":979}}
{"timestamp":"2026-02-07T16:16:44.505Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"706954a8-7339-4121-9667-c0f47059963b","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1507}}
{"timestamp":"2026-02-07T16:16:43.160Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:32.338Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"be0e1d49-1aba-4c32-8f3e-6478ae68e50c","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1740}}
{"timestamp":"2026-02-07T16:16:30.807Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:46.315Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.48","message":"GET / 200","requestId":"b41a96f9-7a2e-4f7e-acb4-c41606501b1d","durationMs":1045,"project_slug":"codersociety","request_url":"/","domain":"veryfront-renderer","project_id":"6ba0cf13-d07b-494c-9d9d-71175e9be870","release_id":"cadf6945-7345-4202-a951-1b52efe3c025","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","method":"GET","statusCode":200,"env":"production"}}
{"timestamp":"2026-02-07T16:16:46.315Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.48","message":"[ContentMetrics] REQUEST_SUMMARY","requestId":"b41a96f9-7a2e-4f7e-acb4-c41606501b1d","durationMs":1045,"project_slug":"codersociety","request_url":"http://veryfront-renderer/","domain":"veryfront-renderer","project_id":"6ba0cf13-d07b-494c-9d9d-71175e9be870","release_id":"cadf6945-7345-4202-a951-1b52efe3c025","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","mode":"production","networkMs":231,"networkTimeRatio":"22%","cacheHitRate":"71%","cacheHits":{"l1_request":0,"l2_persistent":5,"l3_filelist":0},"networkFetches":2,"fetchesByType":{"page":0,"layout":0,"component":0,"api":0,"data":2,"config":0,"other":0},"missReasons":{"cold_start":0,"not_in_filelist":2,"invalidation":0,"no_filelist_cache":0},"uniqueFiles":5,"isPreviewMode":false}}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an accidentally committed runtime log dump. It contains production domains and internal identifiers (projectId/releaseId/requestId), which should not be checked into the repo. Please remove this file from the PR and add an appropriate ignore rule (e.g., logs-*.txt) to prevent future commits.

Suggested change
{"timestamp":"2026-02-07T16:16:46.319Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"309172bb-9bab-437a-83a3-cbe6382eb142","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1199}}
{"timestamp":"2026-02-07T16:16:45.268Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:44.502Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"c72ac1f1-db0d-45c1-8836-95b0414a7ac7","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1409}}
{"timestamp":"2026-02-07T16:16:43.259Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:22.343Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"24f19fe4-8c63-4c0e-9c70-313ea7a5309c","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1076}}
{"timestamp":"2026-02-07T16:16:21.434Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:10.023Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"8b2e7524-cc49-40c3-be2f-156b50de61fb","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":979}}
{"timestamp":"2026-02-07T16:16:44.505Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"706954a8-7339-4121-9667-c0f47059963b","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1507}}
{"timestamp":"2026-02-07T16:16:43.160Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:32.338Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"200 GET /","requestId":"be0e1d49-1aba-4c32-8f3e-6478ae68e50c","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","domain":"codersociety.com","environment":"production","context":{"project":"codersociety","env":"production","ms":1740}}
{"timestamp":"2026-02-07T16:16:30.807Z","level":"info","service":"proxy","veryfrontVersion":"0.1.7-rc.48","message":"Resolved custom domain to project","context":{"domain":"codersociety.com","projectSlug":"codersociety","projectId":"6ba0cf13-d07b-494c-9d9d-71175e9be870","releaseId":"cadf6945-7345-4202-a951-1b52efe3c025","environmentName":"Production"}}
{"timestamp":"2026-02-07T16:16:46.315Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.48","message":"GET / 200","requestId":"b41a96f9-7a2e-4f7e-acb4-c41606501b1d","durationMs":1045,"project_slug":"codersociety","request_url":"/","domain":"veryfront-renderer","project_id":"6ba0cf13-d07b-494c-9d9d-71175e9be870","release_id":"cadf6945-7345-4202-a951-1b52efe3c025","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","method":"GET","statusCode":200,"env":"production"}}
{"timestamp":"2026-02-07T16:16:46.315Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.48","message":"[ContentMetrics] REQUEST_SUMMARY","requestId":"b41a96f9-7a2e-4f7e-acb4-c41606501b1d","durationMs":1045,"project_slug":"codersociety","request_url":"http://veryfront-renderer/","domain":"veryfront-renderer","project_id":"6ba0cf13-d07b-494c-9d9d-71175e9be870","release_id":"cadf6945-7345-4202-a951-1b52efe3c025","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","mode":"production","networkMs":231,"networkTimeRatio":"22%","cacheHitRate":"71%","cacheHits":{"l1_request":0,"l2_persistent":5,"l3_filelist":0},"networkFetches":2,"fetchesByType":{"page":0,"layout":0,"component":0,"api":0,"data":2,"config":0,"other":0},"missReasons":{"cold_start":0,"not_in_filelist":2,"invalidation":0,"no_filelist_cache":0},"uniqueFiles":5,"isPreviewMode":false}}
This file previously contained runtime logs and has been cleared.
Runtime logs must not be committed to the repository. Configure your VCS ignore rules (e.g., logs-*.txt) to prevent future commits.

Copilot uses AI. Check for mistakes.
Comment thread logs-20260206-225100.txt
Comment on lines +1 to +14
{"timestamp":"2026-02-06T21:50:59.704Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"c4b3d471-2a45-4a7f-8339-6e2dd9e9d952","project_slug":"frank-hasselhoff-jpgli","request_url":"http://veryfront-renderer/","domain":"veryfront-renderer","project_id":"0de561b2-ba17-4e18-9bc1-9804f11953a2","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770414659705}"}}
{"timestamp":"2026-02-06T21:50:59.593Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"3e841628-eb5f-4aea-948e-1b44126f61ae","project_slug":"imaginative-lumiere","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"329d43b0-6ee0-49e9-a623-e349767bd45f","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659593}"}}
{"timestamp":"2026-02-06T21:50:59.589Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"deedc254-addb-483b-a2c0-5f0bf11c4915","project_slug":"charming-stroustrup","request_url":"http://veryfront-renderer/_vf_modules/_veryfront/platform/polyfills/node-async-hooks.js","domain":"veryfront-renderer","project_id":"6ad77ae7-a1d3-4ae2-bba5-57400b143047","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/_veryfront/platform/polyfills/node-async-hooks.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659590}"}}
{"timestamp":"2026-02-06T21:50:59.465Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"91c6ce27-d849-45fc-b4a3-3fb993482b8c","project_slug":"sensible-ryker","request_url":"http://veryfront-renderer/_vf_modules/components/app.js","domain":"veryfront-renderer","project_id":"ed4ba9a0-081d-4cfb-b4b2-025ce818cae4","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/app.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659466}"}}
{"timestamp":"2026-02-06T21:50:59.465Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"9d9a5dfb-36f1-4ee6-8f56-5d020a0f94fe","project_slug":"blank","request_url":"http://veryfront-renderer/_vf_modules/components/Welcome.js","domain":"veryfront-renderer","project_id":"68a51dc3-9f2b-40df-aa52-3c242d08b292","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/Welcome.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659466}"}}
{"timestamp":"2026-02-06T21:50:59.460Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"150f5bf1-286b-47aa-9361-833744d525d7","project_slug":"tomcode","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"94af4820-ce16-44e0-9fc4-cd8688f3cc1d","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659461}"}}
{"timestamp":"2026-02-06T21:50:59.455Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"a7d4d917-11e1-4aa8-9287-71d96f614164","project_slug":"reserved-yonath","request_url":"http://veryfront-renderer/_vf_modules/components/app.js","domain":"veryfront-renderer","project_id":"7cef218f-01a1-42a7-8ded-460462b9ee64","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/app.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659455}"}}
{"timestamp":"2026-02-06T21:50:59.445Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"d38796f6-522e-40a8-821f-90bba4266adb","project_slug":"fin-ops","request_url":"http://veryfront-renderer/_vf_modules/components/cost-chart.js","domain":"veryfront-renderer","project_id":"d9cd8eef-e61b-407d-b310-a219bb5bb41d","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/cost-chart.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659446}"}}
{"timestamp":"2026-02-06T21:50:59.437Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"0455ab57-bb79-453f-b97a-a231ce41a656","project_slug":"generous-stroustrup","request_url":"http://veryfront-renderer/_vf_modules/components/Welcome.js","domain":"veryfront-renderer","project_id":"59ba7286-a63a-43be-8636-76dad4378d72","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/Welcome.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659438}"}}
{"timestamp":"2026-02-06T21:50:59.365Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"c82d7565-e144-49e4-a9ac-bf73f1c1dff5","project_slug":"powerful-pike","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770393657213","domain":"veryfront-renderer","project_id":"abac9fda-c07b-4ed7-b071-f74a65fe84d9","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770414659366}"}}
{"timestamp":"2026-02-06T21:50:59.321Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"8c1e0894-39c0-47d9-81d6-ffbc5125f54c","project_slug":"inventive-feynman","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"3349252d-7304-42a2-94f0-19198aec5aae","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659322}"}}
{"timestamp":"2026-02-06T21:50:59.318Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"6dde4379-ef38-4aad-a037-957f1c4e4445","project_slug":"enthusiastic-baracus-fuydu","request_url":"http://veryfront-renderer/?color_mode=light&noHmr=1","domain":"veryfront-renderer","project_id":"0fc24ba4-9799-4bd2-a5ab-a4efeae3e94a","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770414659319}"}}
{"timestamp":"2026-02-06T21:50:59.231Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"92da77b7-6fc1-413f-8299-8fd46cd9f03b","project_slug":"immo-price-finder","request_url":"http://veryfront-renderer/_vf_modules/pages/index.js","domain":"veryfront-renderer","project_id":"2b5730f9-6290-4f23-8731-633458ca06b1","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/pages/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659233}"}}
{"timestamp":"2026-02-06T21:50:59.231Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"4fa8d88f-db40-4a2e-b3f0-b5a7c8ec8545","project_slug":"blank","request_url":"http://veryfront-renderer/_vf_modules/components/Welcome.js","domain":"veryfront-renderer","project_id":"68a51dc3-9f2b-40df-aa52-3c242d08b292","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/Welcome.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659232}"}}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an accidentally committed runtime log dump. It contains internal identifiers and request URLs that shouldn’t be stored in the repo. Please remove this file from the PR and add an ignore rule (e.g., logs-*.txt) to prevent accidental commits.

Suggested change
{"timestamp":"2026-02-06T21:50:59.704Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"c4b3d471-2a45-4a7f-8339-6e2dd9e9d952","project_slug":"frank-hasselhoff-jpgli","request_url":"http://veryfront-renderer/","domain":"veryfront-renderer","project_id":"0de561b2-ba17-4e18-9bc1-9804f11953a2","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770414659705}"}}
{"timestamp":"2026-02-06T21:50:59.593Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"3e841628-eb5f-4aea-948e-1b44126f61ae","project_slug":"imaginative-lumiere","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"329d43b0-6ee0-49e9-a623-e349767bd45f","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659593}"}}
{"timestamp":"2026-02-06T21:50:59.589Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"deedc254-addb-483b-a2c0-5f0bf11c4915","project_slug":"charming-stroustrup","request_url":"http://veryfront-renderer/_vf_modules/_veryfront/platform/polyfills/node-async-hooks.js","domain":"veryfront-renderer","project_id":"6ad77ae7-a1d3-4ae2-bba5-57400b143047","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/_veryfront/platform/polyfills/node-async-hooks.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659590}"}}
{"timestamp":"2026-02-06T21:50:59.465Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"91c6ce27-d849-45fc-b4a3-3fb993482b8c","project_slug":"sensible-ryker","request_url":"http://veryfront-renderer/_vf_modules/components/app.js","domain":"veryfront-renderer","project_id":"ed4ba9a0-081d-4cfb-b4b2-025ce818cae4","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/app.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659466}"}}
{"timestamp":"2026-02-06T21:50:59.465Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"9d9a5dfb-36f1-4ee6-8f56-5d020a0f94fe","project_slug":"blank","request_url":"http://veryfront-renderer/_vf_modules/components/Welcome.js","domain":"veryfront-renderer","project_id":"68a51dc3-9f2b-40df-aa52-3c242d08b292","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/Welcome.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659466}"}}
{"timestamp":"2026-02-06T21:50:59.460Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"150f5bf1-286b-47aa-9361-833744d525d7","project_slug":"tomcode","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"94af4820-ce16-44e0-9fc4-cd8688f3cc1d","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659461}"}}
{"timestamp":"2026-02-06T21:50:59.455Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"a7d4d917-11e1-4aa8-9287-71d96f614164","project_slug":"reserved-yonath","request_url":"http://veryfront-renderer/_vf_modules/components/app.js","domain":"veryfront-renderer","project_id":"7cef218f-01a1-42a7-8ded-460462b9ee64","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/app.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659455}"}}
{"timestamp":"2026-02-06T21:50:59.445Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"d38796f6-522e-40a8-821f-90bba4266adb","project_slug":"fin-ops","request_url":"http://veryfront-renderer/_vf_modules/components/cost-chart.js","domain":"veryfront-renderer","project_id":"d9cd8eef-e61b-407d-b310-a219bb5bb41d","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/cost-chart.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659446}"}}
{"timestamp":"2026-02-06T21:50:59.437Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"0455ab57-bb79-453f-b97a-a231ce41a656","project_slug":"generous-stroustrup","request_url":"http://veryfront-renderer/_vf_modules/components/Welcome.js","domain":"veryfront-renderer","project_id":"59ba7286-a63a-43be-8636-76dad4378d72","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/Welcome.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659438}"}}
{"timestamp":"2026-02-06T21:50:59.365Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"c82d7565-e144-49e4-a9ac-bf73f1c1dff5","project_slug":"powerful-pike","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770393657213","domain":"veryfront-renderer","project_id":"abac9fda-c07b-4ed7-b071-f74a65fe84d9","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770414659366}"}}
{"timestamp":"2026-02-06T21:50:59.321Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"8c1e0894-39c0-47d9-81d6-ffbc5125f54c","project_slug":"inventive-feynman","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"3349252d-7304-42a2-94f0-19198aec5aae","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659322}"}}
{"timestamp":"2026-02-06T21:50:59.318Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"6dde4379-ef38-4aad-a037-957f1c4e4445","project_slug":"enthusiastic-baracus-fuydu","request_url":"http://veryfront-renderer/?color_mode=light&noHmr=1","domain":"veryfront-renderer","project_id":"0fc24ba4-9799-4bd2-a5ab-a4efeae3e94a","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770414659319}"}}
{"timestamp":"2026-02-06T21:50:59.231Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"92da77b7-6fc1-413f-8299-8fd46cd9f03b","project_slug":"immo-price-finder","request_url":"http://veryfront-renderer/_vf_modules/pages/index.js","domain":"veryfront-renderer","project_id":"2b5730f9-6290-4f23-8731-633458ca06b1","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/pages/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659233}"}}
{"timestamp":"2026-02-06T21:50:59.231Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"4fa8d88f-db40-4a2e-b3f0-b5a7c8ec8545","project_slug":"blank","request_url":"http://veryfront-renderer/_vf_modules/components/Welcome.js","domain":"veryfront-renderer","project_id":"68a51dc3-9f2b-40df-aa52-3c242d08b292","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/Welcome.js","data":"{\"type\":\"ping\",\"timestamp\":1770414659232}"}}
This file was previously used to store runtime log output and has been cleared.
Runtime logs must not be committed to the repository.
Please configure your tooling (e.g., .gitignore) to ignore files like logs-*.txt.

Copilot uses AI. Check for mistakes.
Comment thread logs-20260205-182422.txt
Comment on lines +1 to +14
{"timestamp":"2026-02-05T17:24:17.438Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"7dbae5b7-4883-4f9e-bd26-21c4165fdabc","project_slug":"reserved-tesla","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"c7c52e4c-f58e-4553-bd2a-966cab86b946","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770312257438}"}}
{"timestamp":"2026-02-05T17:24:16.453Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"4b6fdf37-0b12-421f-abb5-3185b54379d6","project_slug":"imaginative-lumiere","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770311805608","domain":"veryfront-renderer","project_id":"329d43b0-6ee0-49e9-a623-e349767bd45f","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312256452}"}}
{"timestamp":"2026-02-05T17:24:16.355Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"f4bcde90-cca4-42fa-a188-2515eaad73c0","project_slug":"chatbot-app","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770311805467","domain":"veryfront-renderer","project_id":"96abc62a-6a5e-444f-9356-2ee8010cad85","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312256356}"}}
{"timestamp":"2026-02-05T17:24:14.697Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"9b0474a7-adf9-4563-8fa4-9aa8b892f098","project_slug":"enthusiastic-kirk","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"1d442aa7-171d-4a12-a879-8e3bd7042f29","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312254697}"}}
{"timestamp":"2026-02-05T17:24:20.726Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"8de0923e-9c49-4515-8db8-005d277127df","project_slug":"generous-stroustrup","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770297417477","domain":"veryfront-renderer","project_id":"59ba7286-a63a-43be-8636-76dad4378d72","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312260727}"}}
{"timestamp":"2026-02-05T17:24:20.726Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"95273d95-bb97-4102-8d04-07fb378c12cb","project_slug":"plucky-bohr","request_url":"http://veryfront-renderer/_vf_modules/_veryfront/react/router/index.js","domain":"veryfront-renderer","project_id":"b5a4afe3-9706-4756-bbec-c6fda51f0706","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/_veryfront/react/router/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260726}"}}
{"timestamp":"2026-02-05T17:24:20.726Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"02009ae3-53c7-460e-b5c7-692fcde98b3a","project_slug":"adaptable-bassi","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"e06d2545-e6e9-473f-9721-ca8ac21c89a5","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260726}"}}
{"timestamp":"2026-02-05T17:24:20.725Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"45d3a8d2-bf8e-4971-a108-441b013c0a1a","project_slug":"blank","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"68a51dc3-9f2b-40df-aa52-3c242d08b292","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260726}"}}
{"timestamp":"2026-02-05T17:24:20.724Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"a5bc7035-5e27-4422-95b2-2a8296ea6f33","project_slug":"powerful-pike","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"abac9fda-c07b-4ed7-b071-f74a65fe84d9","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260724}"}}
{"timestamp":"2026-02-05T17:24:20.724Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"b2f916c1-1be6-4ab4-b5ec-d4006a46bea8","project_slug":"communicative-easley-yygxy","request_url":"http://veryfront-renderer/","domain":"veryfront-renderer","project_id":"ff98cb27-9ad1-4486-9352-e7e78563e40d","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260724}"}}
{"timestamp":"2026-02-05T17:24:20.360Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"39b6af9a-0445-4e0f-bc5c-49fbc5b262d7","project_slug":"codersociety","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"6ba0cf13-d07b-494c-9d9d-71175e9be870","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260359}"}}
{"timestamp":"2026-02-05T17:24:20.359Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"a2dcc07b-2316-40d8-a119-4c6118df7dd7","project_slug":"reserved-yonath","request_url":"http://veryfront-renderer/_vf_modules/pages/index.js","domain":"veryfront-renderer","project_id":"7cef218f-01a1-42a7-8ded-460462b9ee64","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/pages/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260359}"}}
{"timestamp":"2026-02-05T17:24:20.359Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"26c2a241-aace-432f-a51a-664395098710","project_slug":"impartial-poincare","request_url":"http://veryfront-renderer/_vf_modules/pages/index.js","domain":"veryfront-renderer","project_id":"fd8b70e7-c978-4051-9212-9aef29727180","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/pages/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260358}"}}
{"timestamp":"2026-02-05T17:24:20.357Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"3dad74a2-68a8-485f-9c4d-0cd285eb46a6","project_slug":"inventive-feynman","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770297417673","domain":"veryfront-renderer","project_id":"3349252d-7304-42a2-94f0-19198aec5aae","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312260357}"}}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an accidentally committed runtime log dump. It includes internal identifiers and request metadata that shouldn’t be checked into the repo. Please remove this file from the PR and add an ignore rule (e.g., logs-*.txt) to prevent future commits.

Suggested change
{"timestamp":"2026-02-05T17:24:17.438Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"7dbae5b7-4883-4f9e-bd26-21c4165fdabc","project_slug":"reserved-tesla","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"c7c52e4c-f58e-4553-bd2a-966cab86b946","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770312257438}"}}
{"timestamp":"2026-02-05T17:24:16.453Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"4b6fdf37-0b12-421f-abb5-3185b54379d6","project_slug":"imaginative-lumiere","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770311805608","domain":"veryfront-renderer","project_id":"329d43b0-6ee0-49e9-a623-e349767bd45f","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312256452}"}}
{"timestamp":"2026-02-05T17:24:16.355Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"f4bcde90-cca4-42fa-a188-2515eaad73c0","project_slug":"chatbot-app","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770311805467","domain":"veryfront-renderer","project_id":"96abc62a-6a5e-444f-9356-2ee8010cad85","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312256356}"}}
{"timestamp":"2026-02-05T17:24:14.697Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"9b0474a7-adf9-4563-8fa4-9aa8b892f098","project_slug":"enthusiastic-kirk","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"1d442aa7-171d-4a12-a879-8e3bd7042f29","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312254697}"}}
{"timestamp":"2026-02-05T17:24:20.726Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"8de0923e-9c49-4515-8db8-005d277127df","project_slug":"generous-stroustrup","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770297417477","domain":"veryfront-renderer","project_id":"59ba7286-a63a-43be-8636-76dad4378d72","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312260727}"}}
{"timestamp":"2026-02-05T17:24:20.726Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"95273d95-bb97-4102-8d04-07fb378c12cb","project_slug":"plucky-bohr","request_url":"http://veryfront-renderer/_vf_modules/_veryfront/react/router/index.js","domain":"veryfront-renderer","project_id":"b5a4afe3-9706-4756-bbec-c6fda51f0706","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/_veryfront/react/router/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260726}"}}
{"timestamp":"2026-02-05T17:24:20.726Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"02009ae3-53c7-460e-b5c7-692fcde98b3a","project_slug":"adaptable-bassi","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"e06d2545-e6e9-473f-9721-ca8ac21c89a5","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260726}"}}
{"timestamp":"2026-02-05T17:24:20.725Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"45d3a8d2-bf8e-4971-a108-441b013c0a1a","project_slug":"blank","request_url":"http://veryfront-renderer/_vf_modules/components/layout.js","domain":"veryfront-renderer","project_id":"68a51dc3-9f2b-40df-aa52-3c242d08b292","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/components/layout.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260726}"}}
{"timestamp":"2026-02-05T17:24:20.724Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"a5bc7035-5e27-4422-95b2-2a8296ea6f33","project_slug":"powerful-pike","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"abac9fda-c07b-4ed7-b071-f74a65fe84d9","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260724}"}}
{"timestamp":"2026-02-05T17:24:20.724Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"b2f916c1-1be6-4ab4-b5ec-d4006a46bea8","project_slug":"communicative-easley-yygxy","request_url":"http://veryfront-renderer/","domain":"veryfront-renderer","project_id":"ff98cb27-9ad1-4486-9352-e7e78563e40d","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260724}"}}
{"timestamp":"2026-02-05T17:24:20.360Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"39b6af9a-0445-4e0f-bc5c-49fbc5b262d7","project_slug":"codersociety","request_url":"http://veryfront-renderer/?color_mode=dark&noHmr=1","domain":"veryfront-renderer","project_id":"6ba0cf13-d07b-494c-9d9d-71175e9be870","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/","data":"{\"type\":\"ping\",\"timestamp\":1770312260359}"}}
{"timestamp":"2026-02-05T17:24:20.359Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"a2dcc07b-2316-40d8-a119-4c6118df7dd7","project_slug":"reserved-yonath","request_url":"http://veryfront-renderer/_vf_modules/pages/index.js","domain":"veryfront-renderer","project_id":"7cef218f-01a1-42a7-8ded-460462b9ee64","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/pages/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260359}"}}
{"timestamp":"2026-02-05T17:24:20.359Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"26c2a241-aace-432f-a51a-664395098710","project_slug":"impartial-poincare","request_url":"http://veryfront-renderer/_vf_modules/pages/index.js","domain":"veryfront-renderer","project_id":"fd8b70e7-c978-4051-9212-9aef29727180","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_modules/pages/index.js","data":"{\"type\":\"ping\",\"timestamp\":1770312260358}"}}
{"timestamp":"2026-02-05T17:24:20.357Z","level":"info","service":"server","veryfrontVersion":"0.1.7-rc.46","message":"[WebSocketManager] WebSocket message received:","requestId":"3dad74a2-68a8-485f-9c4d-0cd285eb46a6","project_slug":"inventive-feynman","request_url":"http://veryfront-renderer/_vf_styles/styles.css?t=1770297417673","domain":"veryfront-renderer","project_id":"3349252d-7304-42a2-94f0-19198aec5aae","release_id":"undefined","branch_id":"undefined","branch_name":"undefined","context":{"pathname":"/_vf_styles/styles.css","data":"{\"type\":\"ping\",\"timestamp\":1770312260357}"}}
This file previously contained runtime log output with internal identifiers and request metadata.
Runtime logs should not be committed to the repository. Please configure your VCS ignore rules
(for example, by adding `logs-*.txt` to .gitignore or an equivalent mechanism) to prevent
future commits of log files.

Copilot uses AI. Check for mistakes.
Comment on lines 14 to +21
const VERYFRONT_CLIENT_MODULES = [
"veryfront/agent/react",
"veryfront/components/ai",
"veryfront/primitives",
"veryfront/head",
"veryfront/router",
"veryfront/context",
"veryfront/fonts",

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR adds new entries to VERYFRONT_CLIENT_MODULES, but the existing unit test fixture list in build-context.test.ts still only asserts the original three modules. This can let future regressions slip through (e.g., if one of the newly added modules is removed from externals). Please update the tests to include the new veryfront/* modules in the expected list for cdn/self-hosted, and ensure they are excluded in bundled mode.

Copilot uses AI. Check for mistakes.
@@ -10,7 +10,7 @@
"shared/mount-react-app.tsx": "import type { ReactNode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nexport function mountReactApp(app: ReactNode): void {\n const root = document.getElementById(\"root\");\n\n if (!root) {\n throw new Error('Root element with id \"root\" not found');\n }\n\n createRoot(root).render(app);\n}\n",
"dashboard/index.tsx": "import { App } from \"./App.tsx\";\nimport { mountReactApp } from \"../shared/mount-react-app.tsx\";\n\nmountReactApp(<App />);\n",
"dashboard/App.tsx": "import { useEffect, useState } from \"react\";\nimport { Header } from \"./components/Header.tsx\";\nimport { TabNav } from \"./components/TabNav.tsx\";\nimport { AITab } from \"./components/AITab.tsx\";\nimport { ServerTab } from \"./components/ServerTab.tsx\";\nimport { RuntimeTab } from \"./components/RuntimeTab.tsx\";\nimport { FilesTab } from \"./components/FilesTab.tsx\";\nimport { ErrorsTab } from \"./components/ErrorsTab.tsx\";\nimport { ConfigTab } from \"./components/ConfigTab.tsx\";\nimport { APITab } from \"./components/APITab.tsx\";\n\nexport interface Tool {\n id: string;\n type: string;\n description: string;\n schema: { properties?: Record<string, unknown>; required?: string[] } | null;\n mcp: { enabled: boolean };\n}\n\nexport interface Resource {\n id: string;\n pattern: string;\n description: string;\n mcp: { enabled: boolean };\n}\n\nexport interface Prompt {\n id: string;\n description: string;\n}\n\nexport interface Agent {\n id: string;\n description: string;\n model: string;\n system: string | null;\n tools: Record<string, boolean>;\n memory: { type: string; maxTokens: number } | null;\n streaming: boolean;\n maxSteps: number | null;\n}\n\nexport interface FileItem {\n name: string;\n type: \"file\" | \"directory\";\n path: string;\n}\n\nexport interface Handler {\n name: string;\n priority: number;\n patterns: Array<{ pattern: string; exact?: boolean; prefix?: boolean; method?: string }>;\n enabled: string;\n}\n\nexport type TabId = \"ai\" | \"server\" | \"runtime\" | \"files\" | \"errors\" | \"config\" | \"api\";\n\nconst TABS: Array<{ id: TabId; label: string }> = [\n { id: \"ai\", label: \"AI\" },\n { id: \"server\", label: \"Server\" },\n { id: \"runtime\", label: \"Runtime\" },\n { id: \"files\", label: \"Files\" },\n { id: \"errors\", label: \"Errors\" },\n { id: \"config\", label: \"Config\" },\n { id: \"api\", label: \"API\" },\n];\n\nasync function fetchJson(url: string): Promise<unknown> {\n const res = await fetch(url);\n return res.json();\n}\n\nexport function App(): JSX.Element {\n const [currentTab, setCurrentTab] = useState<TabId>(\"ai\");\n const [tools, setTools] = useState<Tool[]>([]);\n const [resources, setResources] = useState<Resource[]>([]);\n const [prompts, setPrompts] = useState<Prompt[]>([]);\n const [agents, setAgents] = useState<Agent[]>([]);\n\n useEffect((): void => {\n async function fetchData(): Promise<void> {\n try {\n const [t, r, p, a] = await Promise.all([\n fetchJson(\"/_dev/api/tools\"),\n fetchJson(\"/_dev/api/resources\"),\n fetchJson(\"/_dev/api/prompts\"),\n fetchJson(\"/_dev/api/agents\"),\n ]);\n\n setTools((t as any)?.tools ?? []);\n setResources((r as any)?.resources ?? []);\n setPrompts((p as any)?.prompts ?? []);\n setAgents((a as any)?.agents ?? []);\n } catch (e) {\n console.error(\"Failed to fetch data:\", e);\n }\n }\n\n void fetchData();\n }, []);\n\n return (\n <div className=\"min-h-screen bg-gray-50\">\n <Header />\n <TabNav tabs={TABS} currentTab={currentTab} onTabChange={setCurrentTab} />\n\n <div className=\"tab-content\">\n {currentTab === \"ai\" && (\n <AITab tools={tools} resources={resources} prompts={prompts} agents={agents} />\n )}\n {currentTab === \"server\" && <ServerTab />}\n {currentTab === \"runtime\" && <RuntimeTab />}\n {currentTab === \"files\" && <FilesTab />}\n {currentTab === \"errors\" && <ErrorsTab />}\n {currentTab === \"config\" && <ConfigTab />}\n {currentTab === \"api\" && <APITab />}\n </div>\n </div>\n );\n}\n",
"dashboard/components/MCPTab.tsx": "import { useEffect, useState } from \"react\";\nimport type { Prompt, Resource, Tool } from \"../App.tsx\";\nimport { Sidebar } from \"./Sidebar.tsx\";\nimport { Card } from \"./Card.tsx\";\nimport { ActionButton, DetailHeader, EmptyState, ResultBox, TwoColumnLayout } from \"./shared.tsx\";\n\ntype SubTab = \"tools\" | \"resources\" | \"prompts\";\n\ninterface MCPTabProps {\n tools: Tool[];\n resources: Resource[];\n prompts: Prompt[];\n}\n\nfunction getItemId(item: Tool | Resource | Prompt): string {\n return \"id\" in item ? item.id : item.pattern;\n}\n\nfunction isTool(item: Tool | Resource | Prompt): item is Tool {\n return \"schema\" in item;\n}\n\nfunction isResource(item: Tool | Resource | Prompt): item is Resource {\n return \"pattern\" in item;\n}\n\nfunction isPrompt(item: Tool | Resource | Prompt): item is Prompt {\n return \"id\" in item && !(\"schema\" in item);\n}\n\nexport function MCPTab({ tools, resources, prompts }: MCPTabProps): JSX.Element {\n const [subTab, setSubTab] = useState<SubTab>(\"tools\");\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [search, setSearch] = useState(\"\");\n\n useEffect(() => {\n function handleNavigate(e: CustomEvent<{ subTab: SubTab; itemId: string }>): void {\n setSubTab(e.detail.subTab);\n setSelectedId(e.detail.itemId);\n }\n\n const listener = handleNavigate as unknown as EventListener;\n globalThis.addEventListener(\"mcp-navigate\", listener);\n return () => globalThis.removeEventListener(\"mcp-navigate\", listener);\n }, []);\n\n let items: Array<Tool | Resource | Prompt>;\n if (subTab === \"tools\") items = tools;\n else if (subTab === \"resources\") items = resources;\n else items = prompts;\n\n const searchLower = search.toLowerCase();\n const filteredItems = items.filter((item) => getItemId(item).toLowerCase().includes(searchLower));\n const selectedItem = items.find((item) => getItemId(item) === selectedId);\n\n function renderDetail(): JSX.Element {\n if (!selectedItem) return <EmptyState message=\"Select an item to inspect\" />;\n\n if (subTab === \"tools\" && isTool(selectedItem)) return <ToolDetail tool={selectedItem} />;\n if (subTab === \"resources\" && isResource(selectedItem)) {\n return <ResourceDetail resource={selectedItem} />;\n }\n if (subTab === \"prompts\" && isPrompt(selectedItem)) {\n return <PromptDetail prompt={selectedItem} />;\n }\n\n return <EmptyState message=\"Select an item to inspect\" />;\n }\n\n const sidebar = (\n <Sidebar\n search={search}\n onSearchChange={setSearch}\n subTabs={[\n { id: \"tools\", label: `Tools (${tools.length})` },\n { id: \"resources\", label: `Resources (${resources.length})` },\n { id: \"prompts\", label: `Prompts (${prompts.length})` },\n ]}\n currentSubTab={subTab}\n onSubTabChange={(id) => {\n setSubTab(id as SubTab);\n setSelectedId(null);\n }}\n items={filteredItems.map((item) => {\n const id = getItemId(item);\n return { id, label: id };\n })}\n selectedId={selectedId}\n onSelect={setSelectedId}\n emptyMessage={`No ${subTab} registered`}\n />\n );\n\n return <TwoColumnLayout sidebar={sidebar}>{renderDetail()}</TwoColumnLayout>;\n}\n\nfunction generateExampleFromSchema(schema: Tool[\"schema\"]): Record<string, unknown> {\n if (!schema?.properties) return {};\n\n const example: Record<string, unknown> = {};\n\n for (const [name, prop] of Object.entries(schema.properties)) {\n const propDef = prop as { type?: string; default?: unknown; enum?: unknown[] };\n\n if (propDef.default !== undefined) {\n example[name] = propDef.default;\n continue;\n }\n\n if (propDef.enum?.length) {\n example[name] = propDef.enum[0];\n continue;\n }\n\n switch (propDef.type) {\n case \"string\":\n example[name] = `example-${name}`;\n break;\n case \"number\":\n case \"integer\":\n example[name] = 1;\n break;\n case \"boolean\":\n example[name] = true;\n break;\n case \"array\":\n example[name] = [];\n break;\n case \"object\":\n example[name] = {};\n break;\n default:\n example[name] = null;\n }\n }\n\n return example;\n}\n\nfunction ToolDetail({ tool }: { tool: Tool }): JSX.Element {\n const [args, setArgs] = useState(() => {\n const example = generateExampleFromSchema(tool.schema);\n return JSON.stringify(example, null, 2);\n });\n const [result, setResult] = useState<\n { success: boolean; data: string; duration?: number } | null\n >(\n null,\n );\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n const example = generateExampleFromSchema(tool.schema);\n setArgs(JSON.stringify(example, null, 2));\n setResult(null);\n }, [tool.id, tool.schema]);\n\n async function execute(): Promise<void> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(args);\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n return;\n }\n\n setLoading(true);\n try {\n const res = await fetch(\"/_dev/api/execute-tool\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ toolId: tool.id, args: parsed }),\n });\n const d = await res.json();\n\n if (d.error) {\n setResult({ success: false, data: d.error });\n return;\n }\n\n setResult({\n success: true,\n data: JSON.stringify(d.result, null, 2),\n duration: d.duration,\n });\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div>\n <DetailHeader title={tool.id} description={tool.description || \"No description\"} />\n\n {tool.schema?.properties && (\n <Card title=\"Input Schema\" className=\"mb-6\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"bg-gray-50 border-b\">\n <th className=\"text-left px-3 py-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500\">\n Name\n </th>\n <th className=\"text-left px-3 py-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500\">\n Type\n </th>\n <th className=\"text-left px-3 py-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500\">\n Description\n </th>\n </tr>\n </thead>\n <tbody>\n {Object.entries(tool.schema.properties).map(([name, prop]) => {\n const p = prop as { type?: string; description?: string };\n return (\n <tr key={name} className=\"border-b last:border-0\">\n <td className=\"px-3 py-2.5\">\n <code className=\"text-xs text-sky-600 font-medium\">{name}</code>\n {tool.schema?.required?.includes(name) && (\n <span className=\"ml-1.5 px-1 py-0.5 bg-red-50 text-red-600 text-[9px] font-semibold uppercase rounded\">\n required\n </span>\n )}\n </td>\n <td className=\"px-3 py-2.5\">\n <span className=\"px-1.5 py-0.5 bg-gray-100 text-gray-500 text-[10px] font-medium font-mono rounded\">\n {p.type || \"any\"}\n </span>\n </td>\n <td className=\"px-3 py-2.5 text-gray-600\">{p.description || \"-\"}</td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </Card>\n )}\n\n <Card title=\"Execute\">\n <div className=\"p-4\">\n <label className=\"block text-xs font-medium uppercase tracking-wide text-gray-600 mb-1\">\n Arguments (JSON)\n </label>\n <textarea\n value={args}\n onChange={(e) => setArgs(e.target.value)}\n className=\"w-full px-3 py-2 bg-gray-50 border border-gray-200 rounded text-sm font-mono focus:outline-none focus:border-sky-500 focus:bg-white min-h-[80px] resize-y\"\n />\n <ActionButton onClick={execute} loading={loading} loadingText=\"Running...\">\n Run\n </ActionButton>\n {result && (\n <ResultBox\n success={result.success}\n label={result.success ? \"Success\" : \"Error\"}\n duration={result.duration}\n >\n {result.data}\n </ResultBox>\n )}\n </div>\n </Card>\n </div>\n );\n}\n\nfunction ResourceDetail({ resource }: { resource: Resource }): JSX.Element {\n const [uri, setUri] = useState(resource.pattern);\n const [result, setResult] = useState<\n { success: boolean; data: string; duration?: number } | null\n >(\n null,\n );\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n setUri(resource.pattern);\n setResult(null);\n }, [resource.pattern]);\n\n async function read(): Promise<void> {\n setLoading(true);\n try {\n const res = await fetch(\"/_dev/api/read-resource\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ uri }),\n });\n const d = await res.json();\n\n if (d.error) {\n setResult({ success: false, data: d.error });\n return;\n }\n\n setResult({\n success: true,\n data: JSON.stringify(d.data, null, 2),\n duration: d.duration,\n });\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div>\n <DetailHeader\n title={resource.pattern}\n description={resource.description || \"No description\"}\n />\n\n <Card title=\"Read Resource\">\n <div className=\"p-4\">\n <label className=\"block text-xs font-medium uppercase tracking-wide text-gray-600 mb-1\">\n URI\n </label>\n <input\n type=\"text\"\n value={uri}\n onChange={(e) => setUri(e.target.value)}\n className=\"w-full px-3 py-2 bg-gray-50 border border-gray-200 rounded text-sm focus:outline-none focus:border-sky-500 focus:bg-white\"\n />\n <ActionButton onClick={read} loading={loading} loadingText=\"Reading...\">\n Read\n </ActionButton>\n {result && (\n <ResultBox\n success={result.success}\n label={result.success ? \"Success\" : \"Error\"}\n duration={result.duration}\n >\n {result.data}\n </ResultBox>\n )}\n </div>\n </Card>\n </div>\n );\n}\n\nfunction PromptDetail({ prompt }: { prompt: Prompt }): JSX.Element {\n const [variables, setVariables] = useState(\"{}\");\n const [result, setResult] = useState<{ success: boolean; data: string } | null>(null);\n const [loading, setLoading] = useState(false);\n\n async function render(): Promise<void> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(variables);\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n return;\n }\n\n setLoading(true);\n try {\n const res = await fetch(\"/_dev/api/render-prompt\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ promptId: prompt.id, variables: parsed }),\n });\n const d = await res.json();\n\n if (d.error) {\n setResult({ success: false, data: d.error });\n return;\n }\n\n setResult({ success: true, data: d.content });\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div>\n <DetailHeader title={prompt.id} description={prompt.description || \"No description\"} />\n\n <Card title=\"Render Prompt\">\n <div className=\"p-4\">\n <label className=\"block text-xs font-medium uppercase tracking-wide text-gray-600 mb-1\">\n Variables (JSON)\n </label>\n <textarea\n value={variables}\n onChange={(e) => setVariables(e.target.value)}\n className=\"w-full px-3 py-2 bg-gray-50 border border-gray-200 rounded text-sm font-mono focus:outline-none focus:border-sky-500 focus:bg-white min-h-[80px] resize-y\"\n />\n <ActionButton onClick={render} loading={loading} loadingText=\"Rendering...\">\n Render\n </ActionButton>\n {result && (\n <ResultBox success={result.success} label={result.success ? \"Rendered\" : \"Error\"}>\n {result.data}\n </ResultBox>\n )}\n </div>\n </Card>\n </div>\n );\n}\n",
"dashboard/components/MCPTab.tsx": "import { useEffect, useState } from \"react\";\nimport type { Prompt, Resource, Tool } from \"../App.tsx\";\nimport { Sidebar } from \"./Sidebar.tsx\";\nimport { Card } from \"./Card.tsx\";\nimport { ActionButton, DetailHeader, EmptyState, ResultBox, TwoColumnLayout } from \"./shared.tsx\";\n\ntype SubTab = \"tools\" | \"resources\" | \"prompts\";\n\ninterface MCPTabProps {\n tools: Tool[];\n resources: Resource[];\n prompts: Prompt[];\n}\n\nfunction getItemId(item: Tool | Resource | Prompt): string {\n return \"pattern\" in item ? item.pattern : item.id;\n}\n\nfunction isTool(item: Tool | Resource | Prompt): item is Tool {\n return \"schema\" in item;\n}\n\nfunction isResource(item: Tool | Resource | Prompt): item is Resource {\n return \"pattern\" in item;\n}\n\nfunction isPrompt(item: Tool | Resource | Prompt): item is Prompt {\n return \"id\" in item && !(\"schema\" in item);\n}\n\nexport function MCPTab({ tools, resources, prompts }: MCPTabProps): JSX.Element {\n const [subTab, setSubTab] = useState<SubTab>(\"tools\");\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [search, setSearch] = useState(\"\");\n\n useEffect(() => {\n function handleNavigate(e: CustomEvent<{ subTab: SubTab; itemId: string }>): void {\n setSubTab(e.detail.subTab);\n setSelectedId(e.detail.itemId);\n }\n\n const listener = handleNavigate as unknown as EventListener;\n globalThis.addEventListener(\"mcp-navigate\", listener);\n return () => globalThis.removeEventListener(\"mcp-navigate\", listener);\n }, []);\n\n let items: Array<Tool | Resource | Prompt>;\n if (subTab === \"tools\") items = tools;\n else if (subTab === \"resources\") items = resources;\n else items = prompts;\n\n const searchLower = search.toLowerCase();\n const filteredItems = items.filter((item) => getItemId(item).toLowerCase().includes(searchLower));\n const selectedItem = items.find((item) => getItemId(item) === selectedId);\n\n function renderDetail(): JSX.Element {\n if (!selectedItem) return <EmptyState message=\"Select an item to inspect\" />;\n\n if (subTab === \"tools\" && isTool(selectedItem)) return <ToolDetail tool={selectedItem} />;\n if (subTab === \"resources\" && isResource(selectedItem)) {\n return <ResourceDetail resource={selectedItem} />;\n }\n if (subTab === \"prompts\" && isPrompt(selectedItem)) {\n return <PromptDetail prompt={selectedItem} />;\n }\n\n return <EmptyState message=\"Select an item to inspect\" />;\n }\n\n const sidebar = (\n <Sidebar\n search={search}\n onSearchChange={setSearch}\n subTabs={[\n { id: \"tools\", label: `Tools (${tools.length})` },\n { id: \"resources\", label: `Resources (${resources.length})` },\n { id: \"prompts\", label: `Prompts (${prompts.length})` },\n ]}\n currentSubTab={subTab}\n onSubTabChange={(id) => {\n setSubTab(id as SubTab);\n setSelectedId(null);\n }}\n items={filteredItems.map((item) => {\n const id = getItemId(item);\n return { id, label: id };\n })}\n selectedId={selectedId}\n onSelect={setSelectedId}\n emptyMessage={`No ${subTab} registered`}\n />\n );\n\n return <TwoColumnLayout sidebar={sidebar}>{renderDetail()}</TwoColumnLayout>;\n}\n\nfunction generateExampleFromSchema(schema: Tool[\"schema\"]): Record<string, unknown> {\n if (!schema?.properties) return {};\n\n const example: Record<string, unknown> = {};\n\n for (const [name, prop] of Object.entries(schema.properties)) {\n const propDef = prop as { type?: string; default?: unknown; enum?: unknown[] };\n\n if (propDef.default !== undefined) {\n example[name] = propDef.default;\n continue;\n }\n\n if (propDef.enum?.length) {\n example[name] = propDef.enum[0];\n continue;\n }\n\n switch (propDef.type) {\n case \"string\":\n example[name] = `example-${name}`;\n break;\n case \"number\":\n case \"integer\":\n example[name] = 1;\n break;\n case \"boolean\":\n example[name] = true;\n break;\n case \"array\":\n example[name] = [];\n break;\n case \"object\":\n example[name] = {};\n break;\n default:\n example[name] = null;\n }\n }\n\n return example;\n}\n\nfunction ToolDetail({ tool }: { tool: Tool }): JSX.Element {\n const [args, setArgs] = useState(() => {\n const example = generateExampleFromSchema(tool.schema);\n return JSON.stringify(example, null, 2);\n });\n const [result, setResult] = useState<\n { success: boolean; data: string; duration?: number } | null\n >(\n null,\n );\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n const example = generateExampleFromSchema(tool.schema);\n setArgs(JSON.stringify(example, null, 2));\n setResult(null);\n }, [tool.id, tool.schema]);\n\n async function execute(): Promise<void> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(args);\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n return;\n }\n\n setLoading(true);\n try {\n const res = await fetch(\"/_dev/api/execute-tool\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ toolId: tool.id, args: parsed }),\n });\n const d = await res.json();\n\n if (d.error) {\n setResult({ success: false, data: d.error });\n return;\n }\n\n setResult({\n success: true,\n data: JSON.stringify(d.result, null, 2),\n duration: d.duration,\n });\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div>\n <DetailHeader title={tool.id} description={tool.description || \"No description\"} />\n\n {tool.schema?.properties && (\n <Card title=\"Input Schema\" className=\"mb-6\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"bg-gray-50 border-b\">\n <th className=\"text-left px-3 py-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500\">\n Name\n </th>\n <th className=\"text-left px-3 py-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500\">\n Type\n </th>\n <th className=\"text-left px-3 py-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500\">\n Description\n </th>\n </tr>\n </thead>\n <tbody>\n {Object.entries(tool.schema.properties).map(([name, prop]) => {\n const p = prop as { type?: string; description?: string };\n return (\n <tr key={name} className=\"border-b last:border-0\">\n <td className=\"px-3 py-2.5\">\n <code className=\"text-xs text-sky-600 font-medium\">{name}</code>\n {tool.schema?.required?.includes(name) && (\n <span className=\"ml-1.5 px-1 py-0.5 bg-red-50 text-red-600 text-[9px] font-semibold uppercase rounded\">\n required\n </span>\n )}\n </td>\n <td className=\"px-3 py-2.5\">\n <span className=\"px-1.5 py-0.5 bg-gray-100 text-gray-500 text-[10px] font-medium font-mono rounded\">\n {p.type || \"any\"}\n </span>\n </td>\n <td className=\"px-3 py-2.5 text-gray-600\">{p.description || \"-\"}</td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </Card>\n )}\n\n <Card title=\"Execute\">\n <div className=\"p-4\">\n <label className=\"block text-xs font-medium uppercase tracking-wide text-gray-600 mb-1\">\n Arguments (JSON)\n </label>\n <textarea\n value={args}\n onChange={(e) => setArgs(e.target.value)}\n className=\"w-full px-3 py-2 bg-gray-50 border border-gray-200 rounded text-sm font-mono focus:outline-none focus:border-sky-500 focus:bg-white min-h-[80px] resize-y\"\n />\n <ActionButton onClick={execute} loading={loading} loadingText=\"Running...\">\n Run\n </ActionButton>\n {result && (\n <ResultBox\n success={result.success}\n label={result.success ? \"Success\" : \"Error\"}\n duration={result.duration}\n >\n {result.data}\n </ResultBox>\n )}\n </div>\n </Card>\n </div>\n );\n}\n\nfunction ResourceDetail({ resource }: { resource: Resource }): JSX.Element {\n const [uri, setUri] = useState(resource.pattern);\n const [result, setResult] = useState<\n { success: boolean; data: string; duration?: number } | null\n >(\n null,\n );\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n setUri(resource.pattern);\n setResult(null);\n }, [resource.pattern]);\n\n async function read(): Promise<void> {\n setLoading(true);\n try {\n const res = await fetch(\"/_dev/api/read-resource\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ uri }),\n });\n const d = await res.json();\n\n if (d.error) {\n setResult({ success: false, data: d.error });\n return;\n }\n\n setResult({\n success: true,\n data: JSON.stringify(d.data, null, 2),\n duration: d.duration,\n });\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div>\n <DetailHeader\n title={resource.pattern}\n description={resource.description || \"No description\"}\n />\n\n <Card title=\"Read Resource\">\n <div className=\"p-4\">\n <label className=\"block text-xs font-medium uppercase tracking-wide text-gray-600 mb-1\">\n URI\n </label>\n <input\n type=\"text\"\n value={uri}\n onChange={(e) => setUri(e.target.value)}\n className=\"w-full px-3 py-2 bg-gray-50 border border-gray-200 rounded text-sm focus:outline-none focus:border-sky-500 focus:bg-white\"\n />\n <ActionButton onClick={read} loading={loading} loadingText=\"Reading...\">\n Read\n </ActionButton>\n {result && (\n <ResultBox\n success={result.success}\n label={result.success ? \"Success\" : \"Error\"}\n duration={result.duration}\n >\n {result.data}\n </ResultBox>\n )}\n </div>\n </Card>\n </div>\n );\n}\n\nfunction PromptDetail({ prompt }: { prompt: Prompt }): JSX.Element {\n const [variables, setVariables] = useState(\"{}\");\n const [result, setResult] = useState<{ success: boolean; data: string } | null>(null);\n const [loading, setLoading] = useState(false);\n\n async function render(): Promise<void> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(variables);\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n return;\n }\n\n setLoading(true);\n try {\n const res = await fetch(\"/_dev/api/render-prompt\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ promptId: prompt.id, variables: parsed }),\n });\n const d = await res.json();\n\n if (d.error) {\n setResult({ success: false, data: d.error });\n return;\n }\n\n setResult({ success: true, data: d.content });\n } catch (e) {\n setResult({ success: false, data: (e as Error).message });\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div>\n <DetailHeader title={prompt.id} description={prompt.description || \"No description\"} />\n\n <Card title=\"Render Prompt\">\n <div className=\"p-4\">\n <label className=\"block text-xs font-medium uppercase tracking-wide text-gray-600 mb-1\">\n Variables (JSON)\n </label>\n <textarea\n value={variables}\n onChange={(e) => setVariables(e.target.value)}\n className=\"w-full px-3 py-2 bg-gray-50 border border-gray-200 rounded text-sm font-mono focus:outline-none focus:border-sky-500 focus:bg-white min-h-[80px] resize-y\"\n />\n <ActionButton onClick={render} loading={loading} loadingText=\"Rendering...\">\n Render\n </ActionButton>\n {result && (\n <ResultBox success={result.success} label={result.success ? \"Rendered\" : \"Error\"}>\n {result.data}\n </ResultBox>\n )}\n </div>\n </Card>\n </div>\n );\n}\n",

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR includes substantial unrelated changes embedded in the dev UI manifest (e.g., dashboard component logic/style refactors). Since the PR’s stated purpose is to fix bundler externals, these extra changes make the review/risk surface larger. Consider reverting these manifest changes or splitting them into a separate PR focused on dev-ui updates.

Copilot uses AI. Check for mistakes.
@kwakayama

Copy link
Copy Markdown
Contributor Author

Closing — this PR conflicts with the refactor in #264 (merged to main). The bundler externals issue will be addressed separately if needed.

@kwakayama kwakayama closed this Feb 8, 2026
@kwakayama
kwakayama deleted the fix/bundler-external-veryfront-modules branch February 12, 2026 07:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants