@seqyuan/annodex 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +40 -0
- package/.next/build-manifest.json +20 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +138 -0
- package/.next/react-loadable-manifest.json +2320 -0
- package/.next/required-server-files.js +343 -0
- package/.next/required-server-files.json +343 -0
- package/.next/routes-manifest.json +292 -0
- package/.next/server/app/_global-error/page.js +32 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +16 -0
- package/.next/server/app/_global-error.rsc +14 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +14 -0
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_global-error.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_head.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_index.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page.js +2 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +16 -0
- package/.next/server/app/_not-found.rsc +18 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -0
- package/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_not-found.segments/_index.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/api/agent/[id]/events/route.js +3 -0
- package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/[id]/events/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/agent/[id]/route.js +1 -0
- package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/[id]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/agent/new/route.js +1 -0
- package/.next/server/app/api/agent/new/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/new/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/all-providers/route.js +1 -0
- package/.next/server/app/api/auth/all-providers/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/all-providers/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -0
- package/.next/server/app/api/auth/api-key/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/api-key/[provider]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/login/[provider]/route.js +1 -0
- package/.next/server/app/api/auth/login/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/login/[provider]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/login/route.js +1 -0
- package/.next/server/app/api/auth/login/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/logout/[provider]/route.js +1 -0
- package/.next/server/app/api/auth/logout/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/logout/[provider]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/providers/route.js +1 -0
- package/.next/server/app/api/auth/providers/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/providers/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/status/route.js +1 -0
- package/.next/server/app/api/auth/status/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/default-cwd/route.js +1 -0
- package/.next/server/app/api/default-cwd/route.js.nft.json +1 -0
- package/.next/server/app/api/default-cwd/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/files/[...path]/route.js +4 -0
- package/.next/server/app/api/files/[...path]/route.js.nft.json +1 -0
- package/.next/server/app/api/files/[...path]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/harness/route.js +1 -0
- package/.next/server/app/api/harness/route.js.nft.json +1 -0
- package/.next/server/app/api/harness/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/home/route.js +1 -0
- package/.next/server/app/api/home/route.js.nft.json +1 -0
- package/.next/server/app/api/home/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/internal/runtime/route.js +1 -0
- package/.next/server/app/api/internal/runtime/route.js.nft.json +1 -0
- package/.next/server/app/api/internal/runtime/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models/route.js +1 -0
- package/.next/server/app/api/models/route.js.nft.json +1 -0
- package/.next/server/app/api/models/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models-config/discover/route.js +1 -0
- package/.next/server/app/api/models-config/discover/route.js.nft.json +1 -0
- package/.next/server/app/api/models-config/discover/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models-config/route.js +1 -0
- package/.next/server/app/api/models-config/route.js.nft.json +1 -0
- package/.next/server/app/api/models-config/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models-config/test/route.js +1 -0
- package/.next/server/app/api/models-config/test/route.js.nft.json +1 -0
- package/.next/server/app/api/models-config/test/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/projects/browse/route.js +1 -0
- package/.next/server/app/api/projects/browse/route.js.nft.json +1 -0
- package/.next/server/app/api/projects/browse/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/projects/route.js +1 -0
- package/.next/server/app/api/projects/route.js.nft.json +1 -0
- package/.next/server/app/api/projects/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/reports/[id]/route.js +10 -0
- package/.next/server/app/api/reports/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/reports/[id]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/search/route.js +1 -0
- package/.next/server/app/api/search/route.js.nft.json +1 -0
- package/.next/server/app/api/search/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/context/route.js +1 -0
- package/.next/server/app/api/sessions/[id]/context/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/context/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/route.js +1 -0
- package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/new/route.js +1 -0
- package/.next/server/app/api/sessions/new/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/new/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/route.js +1 -0
- package/.next/server/app/api/sessions/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/settings/route.js +1 -0
- package/.next/server/app/api/settings/route.js.nft.json +1 -0
- package/.next/server/app/api/settings/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/install/route.js +5 -0
- package/.next/server/app/api/skills/install/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/install/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/route.js +1 -0
- package/.next/server/app/api/skills/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/search/route.js +1 -0
- package/.next/server/app/api/skills/search/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/search/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/soul/route.js +1 -0
- package/.next/server/app/api/soul/route.js.nft.json +1 -0
- package/.next/server/app/api/soul/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/version/route.js +1 -0
- package/.next/server/app/api/version/route.js.nft.json +1 -0
- package/.next/server/app/api/version/route_client-reference-manifest.js +1 -0
- package/.next/server/app/favicon.ico/route.js +1 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +14 -0
- package/.next/server/app/index.rsc +17 -0
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +6 -0
- package/.next/server/app/index.segments/_full.segment.rsc +17 -0
- package/.next/server/app/index.segments/_head.segment.rsc +6 -0
- package/.next/server/app/index.segments/_index.segment.rsc +5 -0
- package/.next/server/app/index.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/login/page.js +2 -0
- package/.next/server/app/login/page.js.nft.json +1 -0
- package/.next/server/app/login/page_client-reference-manifest.js +1 -0
- package/.next/server/app/login.html +1 -0
- package/.next/server/app/login.meta +15 -0
- package/.next/server/app/login.rsc +22 -0
- package/.next/server/app/login.segments/_full.segment.rsc +22 -0
- package/.next/server/app/login.segments/_head.segment.rsc +6 -0
- package/.next/server/app/login.segments/_index.segment.rsc +5 -0
- package/.next/server/app/login.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +9 -0
- package/.next/server/app/login.segments/login.segment.rsc +5 -0
- package/.next/server/app/page.js +271 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app-paths-manifest.json +40 -0
- package/.next/server/chunks/1048.js +1 -0
- package/.next/server/chunks/1367.js +77 -0
- package/.next/server/chunks/1381.js +1 -0
- package/.next/server/chunks/165.js +1 -0
- package/.next/server/chunks/1681.js +215 -0
- package/.next/server/chunks/1688.js +45 -0
- package/.next/server/chunks/1703.js +79 -0
- package/.next/server/chunks/1712.js +43 -0
- package/.next/server/chunks/1813.js +1 -0
- package/.next/server/chunks/2325.js +80 -0
- package/.next/server/chunks/258.js +1 -0
- package/.next/server/chunks/2671.js +287 -0
- package/.next/server/chunks/2778.js +1 -0
- package/.next/server/chunks/2943.js +1 -0
- package/.next/server/chunks/3031.js +226 -0
- package/.next/server/chunks/3181.js +1 -0
- package/.next/server/chunks/3451.js +1 -0
- package/.next/server/chunks/3493.js +1 -0
- package/.next/server/chunks/3672.js +1 -0
- package/.next/server/chunks/3701.js +104 -0
- package/.next/server/chunks/4013.js +1 -0
- package/.next/server/chunks/4035.js +80 -0
- package/.next/server/chunks/4248.js +153 -0
- package/.next/server/chunks/4367.js +1 -0
- package/.next/server/chunks/4406.js +141 -0
- package/.next/server/chunks/4741.js +18 -0
- package/.next/server/chunks/4858.js +148 -0
- package/.next/server/chunks/4980.js +1 -0
- package/.next/server/chunks/5155.js +5 -0
- package/.next/server/chunks/5293.js +166 -0
- package/.next/server/chunks/5409.js +1 -0
- package/.next/server/chunks/5582.js +5 -0
- package/.next/server/chunks/5797.js +93 -0
- package/.next/server/chunks/5851.js +36 -0
- package/.next/server/chunks/6206.js +1 -0
- package/.next/server/chunks/6296.js +1 -0
- package/.next/server/chunks/63.js +45 -0
- package/.next/server/chunks/6346.js +1 -0
- package/.next/server/chunks/6406.js +23 -0
- package/.next/server/chunks/642.js +1 -0
- package/.next/server/chunks/6429.js +41 -0
- package/.next/server/chunks/6729.js +64 -0
- package/.next/server/chunks/6907.js +115 -0
- package/.next/server/chunks/6980.js +1 -0
- package/.next/server/chunks/7073.js +24 -0
- package/.next/server/chunks/7233.js +24 -0
- package/.next/server/chunks/7307.js +1 -0
- package/.next/server/chunks/7362.js +9 -0
- package/.next/server/chunks/7567.js +29 -0
- package/.next/server/chunks/7765.js +1 -0
- package/.next/server/chunks/7890.js +1 -0
- package/.next/server/chunks/8065.js +1 -0
- package/.next/server/chunks/8238.js +34 -0
- package/.next/server/chunks/8276.js +1 -0
- package/.next/server/chunks/8336.js +1 -0
- package/.next/server/chunks/8477.js +3 -0
- package/.next/server/chunks/8490.js +1 -0
- package/.next/server/chunks/8916.js +1 -0
- package/.next/server/chunks/9280.js +252 -0
- package/.next/server/chunks/9315.js +1 -0
- package/.next/server/chunks/9537.js +90 -0
- package/.next/server/chunks/966.js +1 -0
- package/.next/server/chunks/9818.js +21 -0
- package/.next/server/chunks/static/media/pdf.worker.min.c476e1a0.mjs +6 -0
- package/.next/server/functions-config-manifest.json +15 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/middleware.js +18 -0
- package/.next/server/middleware.js.nft.json +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/prefetch-hints.json +1 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/MrC_PjcnTCuTz_2z6_wXx/_buildManifest.js +1 -0
- package/.next/static/MrC_PjcnTCuTz_2z6_wXx/_ssgManifest.js +1 -0
- package/.next/static/chunks/0b9a0da7.9075af772487e743.js +62 -0
- package/.next/static/chunks/1413.922d232de90c0c41.js +115 -0
- package/.next/static/chunks/1643.467a526a1f24f54d.js +24 -0
- package/.next/static/chunks/1852.5543122f11aa7fed.js +1 -0
- package/.next/static/chunks/1960.b1e26436d7a5f586.js +1 -0
- package/.next/static/chunks/2170a4aa.4213bb2183c9cdf9.js +1 -0
- package/.next/static/chunks/2274.6cd173f80a1405a2.js +21 -0
- package/.next/static/chunks/2419.347fdfe3c170854d.js +166 -0
- package/.next/static/chunks/2619.9aac8983f30c7c8a.js +1 -0
- package/.next/static/chunks/2623.d20fabd8e18197c6.js +287 -0
- package/.next/static/chunks/2729.f5365061a849d659.js +34 -0
- package/.next/static/chunks/2821.934bcf60fbdc28c6.js +1 -0
- package/.next/static/chunks/2918becc.abff2ece1de37bc1.js +153 -0
- package/.next/static/chunks/2947.114e51cb06d1c01a.js +23 -0
- package/.next/static/chunks/3079.4c511fa1144e3adf.js +79 -0
- package/.next/static/chunks/3274.208ca44844cd7d95.js +148 -0
- package/.next/static/chunks/3308.465a94263d04bfea.js +73 -0
- package/.next/static/chunks/3325.e4bfe1ca657f3b5b.js +80 -0
- package/.next/static/chunks/3506.2a7eaa08b9f55337.js +90 -0
- package/.next/static/chunks/363642f4-043c1475ab9af70e.js +1 -0
- package/.next/static/chunks/3794-123fdf632563f469.js +32 -0
- package/.next/static/chunks/3837.a755ccfe6f9c1c1c.js +5 -0
- package/.next/static/chunks/394.91597771688df6d0.js +1 -0
- package/.next/static/chunks/3997.1009c06025691712.js +1 -0
- package/.next/static/chunks/4453.91a357dc43c21745.js +1 -0
- package/.next/static/chunks/4491.44fdf20580ac72bd.js +24 -0
- package/.next/static/chunks/4829.cf1d50e43e6d9db5.js +1 -0
- package/.next/static/chunks/498.fe1d9da9ecad6c36.js +1 -0
- package/.next/static/chunks/4bd1b696-e356ca5ba0218e27.js +1 -0
- package/.next/static/chunks/5019.b5a1a2b8daf17525.js +1 -0
- package/.next/static/chunks/5034.8f16c3fa3ce75411.js +1 -0
- package/.next/static/chunks/5074.d16651da01ec4e02.js +1 -0
- package/.next/static/chunks/51fb665c.0950e1b79671348d.js +45 -0
- package/.next/static/chunks/532.5956ed631aff722b.js +9 -0
- package/.next/static/chunks/5326.69460442bdcd6cd3.js +1 -0
- package/.next/static/chunks/5403.ff110bf5bf600758.js +64 -0
- package/.next/static/chunks/547.902a733488cfe3f7.js +77 -0
- package/.next/static/chunks/5567.540d7fc108ad6ee5.js +215 -0
- package/.next/static/chunks/5590.ef62922166d308b4.js +1 -0
- package/.next/static/chunks/5690.9d6eb1edb1399995.js +1 -0
- package/.next/static/chunks/5749.25faee4a1e55b854.js +226 -0
- package/.next/static/chunks/58bb9007.1ccb6bba34b4c635.js +80 -0
- package/.next/static/chunks/6121.f3f43f1896ea0cd9.js +1 -0
- package/.next/static/chunks/6600.583c88eef37aa524.js +1 -0
- package/.next/static/chunks/6696.a41aec266e657d54.js +141 -0
- package/.next/static/chunks/6922.42148793782d2fe7.js +1 -0
- package/.next/static/chunks/7006.e191611ffc2b9528.js +43 -0
- package/.next/static/chunks/7343.9fbb58204d8ac681.js +1 -0
- package/.next/static/chunks/73972abe.25a4cffa03b2bcef.js +119 -0
- package/.next/static/chunks/7547.58bda8a2aabba0d4.js +93 -0
- package/.next/static/chunks/7648.4ae2f183b4db0353.js +1 -0
- package/.next/static/chunks/7874.8db6929b94cdf697.js +1 -0
- package/.next/static/chunks/7959.1f20a35df316216a.js +104 -0
- package/.next/static/chunks/83.85d62d7fc9850b75.js +29 -0
- package/.next/static/chunks/8436.cab94b59cca0a8ff.js +1 -0
- package/.next/static/chunks/8451.ff6ff72b57dc52e1.js +1 -0
- package/.next/static/chunks/8489.45f22859734f514f.js +36 -0
- package/.next/static/chunks/8568.f85d8b36fc9a9037.js +1 -0
- package/.next/static/chunks/8771-3e14b6810486df1f.js +1 -0
- package/.next/static/chunks/8863.be51033a67436277.js +1 -0
- package/.next/static/chunks/90542734.dc1a2723e4f6affb.js +1 -0
- package/.next/static/chunks/9500.1488aec06ee78127.js +1 -0
- package/.next/static/chunks/9633.155548b5fca6e580.js +1 -0
- package/.next/static/chunks/9779.673004a62d70e36a.js +1 -0
- package/.next/static/chunks/app/_global-error/page-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/_not-found/page-c72daab99269beff.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/auth/all-providers/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/auth/login/[provider]/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/auth/providers/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/default-cwd/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/files/[...path]/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/harness/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/home/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/internal/runtime/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/models/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/models-config/discover/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/models-config/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/models-config/test/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/projects/browse/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/projects/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/reports/[id]/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/search/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/context/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/sessions/new/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/settings/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/skills/install/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/skills/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/skills/search/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/soul/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/api/version/route-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/app/layout-be148b7ae915b22a.js +1 -0
- package/.next/static/chunks/app/login/page-ebf0e6de99062783.js +1 -0
- package/.next/static/chunks/app/page-9e365f85e549786e.js +270 -0
- package/.next/static/chunks/d3ac728e.7964f816a1ca64e5.js +1 -0
- package/.next/static/chunks/framework-711ef29bc66f648c.js +1 -0
- package/.next/static/chunks/main-app-45a0f19af99d61b6.js +1 -0
- package/.next/static/chunks/main-f74964b7ae52493e.js +5 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-9bfa08b9491621f2.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-cc518af6b1ffb191.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-fcf4a889ecbd753c.js +1 -0
- package/.next/static/css/dc49561245206daf.css +3 -0
- package/.next/static/media/15605e25b523335c-s.woff2 +0 -0
- package/.next/static/media/1a3dce5cfb5f7760-s.woff2 +0 -0
- package/.next/static/media/1cdd02902f937a18-s.woff2 +0 -0
- package/.next/static/media/4c4b3b30b6bcb2be-s.woff2 +0 -0
- package/.next/static/media/641a7b8a5800ee0e-s.woff2 +0 -0
- package/.next/static/media/7deddc85b7ffd1dc-s.p.woff2 +0 -0
- package/.next/static/media/ec14413c594b3356-s.p.woff2 +0 -0
- package/.next/static/media/pdf.worker.min.29aaf158.mjs +6 -0
- package/.next/trace +74 -0
- package/.next/trace-build +1 -0
- package/.next/types/app/api/agent/[id]/events/route.ts +351 -0
- package/.next/types/app/api/agent/[id]/route.ts +351 -0
- package/.next/types/app/api/agent/new/route.ts +351 -0
- package/.next/types/app/api/auth/all-providers/route.ts +351 -0
- package/.next/types/app/api/auth/api-key/[provider]/route.ts +351 -0
- package/.next/types/app/api/auth/login/[provider]/route.ts +351 -0
- package/.next/types/app/api/auth/login/route.ts +351 -0
- package/.next/types/app/api/auth/logout/[provider]/route.ts +351 -0
- package/.next/types/app/api/auth/providers/route.ts +351 -0
- package/.next/types/app/api/auth/status/route.ts +351 -0
- package/.next/types/app/api/default-cwd/route.ts +351 -0
- package/.next/types/app/api/files/[...path]/route.ts +351 -0
- package/.next/types/app/api/harness/route.ts +351 -0
- package/.next/types/app/api/home/route.ts +351 -0
- package/.next/types/app/api/internal/runtime/route.ts +351 -0
- package/.next/types/app/api/models/route.ts +351 -0
- package/.next/types/app/api/models-config/discover/route.ts +351 -0
- package/.next/types/app/api/models-config/route.ts +351 -0
- package/.next/types/app/api/models-config/test/route.ts +351 -0
- package/.next/types/app/api/projects/browse/route.ts +351 -0
- package/.next/types/app/api/projects/route.ts +351 -0
- package/.next/types/app/api/reports/[id]/route.ts +351 -0
- package/.next/types/app/api/search/route.ts +351 -0
- package/.next/types/app/api/sessions/[id]/context/route.ts +351 -0
- package/.next/types/app/api/sessions/[id]/route.ts +351 -0
- package/.next/types/app/api/sessions/new/route.ts +351 -0
- package/.next/types/app/api/sessions/route.ts +351 -0
- package/.next/types/app/api/settings/route.ts +351 -0
- package/.next/types/app/api/skills/install/route.ts +351 -0
- package/.next/types/app/api/skills/route.ts +351 -0
- package/.next/types/app/api/skills/search/route.ts +351 -0
- package/.next/types/app/api/soul/route.ts +351 -0
- package/.next/types/app/api/version/route.ts +351 -0
- package/.next/types/app/layout.ts +87 -0
- package/.next/types/app/login/page.ts +87 -0
- package/.next/types/app/page.ts +87 -0
- package/.next/types/package.json +1 -0
- package/.next/types/routes.d.ts +106 -0
- package/.next/types/validator.ts +376 -0
- package/LICENSE +21 -0
- package/README.md +59 -0
- package/bin/annodex.js +1140 -0
- package/lib/default-HARNESS.md +113 -0
- package/lib/default-SOUL.md +42 -0
- package/next.config.ts +15 -0
- package/package.json +77 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
package/bin/annodex.js
ADDED
|
@@ -0,0 +1,1140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
process.title = "annodex";
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
7
|
+
const { spawn, spawnSync } = require("child_process");
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
9
|
+
const path = require("path");
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
+
const os = require("os");
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
+
const http = require("http");
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
|
+
const net = require("net");
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
19
|
+
const readline = require("readline");
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
|
+
const { parseArgs } = require("util");
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
23
|
+
const bcrypt = require("bcryptjs");
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
25
|
+
const https = require("https");
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
27
|
+
const { randomBytes } = require("crypto");
|
|
28
|
+
|
|
29
|
+
const pkgDir = path.join(__dirname, "..");
|
|
30
|
+
const nextDir = path.join(pkgDir, ".next");
|
|
31
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(pkgDir, "package.json"), "utf8"));
|
|
32
|
+
const VERSION = pkg.version;
|
|
33
|
+
const PKG_NAME = pkg.name;
|
|
34
|
+
function envFirst(...names) {
|
|
35
|
+
for (const name of names) {
|
|
36
|
+
const value = process.env[name];
|
|
37
|
+
if (value !== undefined) return value;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const agentDir = envFirst("ANNODEX_CONFIG_DIR", "ANNOVIBE_CONFIG_DIR") ?? path.join(os.homedir(), ".config", "annodex");
|
|
43
|
+
const authFile = path.join(agentDir, "web-auth.json");
|
|
44
|
+
const stateFile = path.join(agentDir, "annodex.json");
|
|
45
|
+
const legacyStateFiles = [
|
|
46
|
+
path.join(agentDir, "annovibe.json"),
|
|
47
|
+
path.join(agentDir, "pidex.json"),
|
|
48
|
+
];
|
|
49
|
+
const logFile = path.join(agentDir, "annodex.log");
|
|
50
|
+
const legacyLogFiles = [
|
|
51
|
+
path.join(agentDir, "annovibe.log"),
|
|
52
|
+
path.join(agentDir, "pidex.log"),
|
|
53
|
+
];
|
|
54
|
+
const STOP_TERM_TIMEOUT_MS = 6000;
|
|
55
|
+
const STOP_KILL_TIMEOUT_MS = 2000;
|
|
56
|
+
const PROCESS_TITLE = "annodex";
|
|
57
|
+
const NEXT_PROCESS_TITLE = "annodex-next";
|
|
58
|
+
const AUTO_RESTART_ENABLED = !/^(0|false|no)$/i.test(envFirst("ANNODEX_AUTO_RESTART", "ANNOVIBE_AUTO_RESTART") ?? "1");
|
|
59
|
+
const AUTO_RESTART_POLL_MS = parsePositiveInt(envFirst("ANNODEX_AUTO_RESTART_POLL_MS", "ANNOVIBE_AUTO_RESTART_POLL_MS"), 60_000);
|
|
60
|
+
const AUTO_RESTART_IDLE_GRACE_MS = parsePositiveInt(envFirst("ANNODEX_AUTO_RESTART_IDLE_GRACE_MS", "ANNOVIBE_AUTO_RESTART_IDLE_GRACE_MS"), 10_000);
|
|
61
|
+
const AUTO_RESTART_MAX_WAIT_MS = parsePositiveInt(envFirst("ANNODEX_AUTO_RESTART_MAX_WAIT_MS", "ANNOVIBE_AUTO_RESTART_MAX_WAIT_MS"), 30 * 60_000);
|
|
62
|
+
const AUTO_RESTART_WAIT_FOR_PORT_MS = parsePositiveInt(envFirst("ANNODEX_AUTO_RESTART_WAIT_FOR_PORT_MS", "ANNOVIBE_AUTO_RESTART_WAIT_FOR_PORT_MS"), 30_000);
|
|
63
|
+
const INTERNAL_RUNTIME_TIMEOUT_MS = 3000;
|
|
64
|
+
|
|
65
|
+
// Resolve next's CLI entry
|
|
66
|
+
let nextBin;
|
|
67
|
+
try {
|
|
68
|
+
nextBin = require.resolve("next/dist/bin/next", { paths: [pkgDir] });
|
|
69
|
+
} catch {
|
|
70
|
+
try {
|
|
71
|
+
const nextPkg = require.resolve("next/package.json", { paths: [pkgDir] });
|
|
72
|
+
nextBin = path.join(path.dirname(nextPkg), "dist", "bin", "next");
|
|
73
|
+
} catch {
|
|
74
|
+
nextBin = path.join(pkgDir, "node_modules", "next", "dist", "bin", "next");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const { values: cliArgs, positionals } = parseArgs({
|
|
79
|
+
options: {
|
|
80
|
+
port: { type: "string", short: "p" },
|
|
81
|
+
hostname: { type: "string", short: "H" },
|
|
82
|
+
json: { type: "boolean" },
|
|
83
|
+
follow: { type: "boolean", short: "f" },
|
|
84
|
+
version: { type: "boolean", short: "v" },
|
|
85
|
+
help: { type: "boolean", short: "h" },
|
|
86
|
+
},
|
|
87
|
+
strict: false,
|
|
88
|
+
allowPositionals: true,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const port = cliArgs.port ?? process.env.PORT ?? "30141";
|
|
92
|
+
const hostname = cliArgs.hostname ?? process.env.HOSTNAME ?? null;
|
|
93
|
+
|
|
94
|
+
// ── CLI commands ──
|
|
95
|
+
|
|
96
|
+
function ensureAgentDir() {
|
|
97
|
+
if (!fs.existsSync(agentDir)) fs.mkdirSync(agentDir, { recursive: true });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getCommandPath() {
|
|
101
|
+
return path.resolve(process.argv[1] || __filename);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getUrl(host, listenPort) {
|
|
105
|
+
return `http://${host ?? "localhost"}:${listenPort}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getServerArgs() {
|
|
109
|
+
return [getCommandPath(), "__server", "--port", String(port), ...(hostname ? ["--hostname", hostname] : [])];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function getServerCommand() {
|
|
113
|
+
return `${getCommandPath()} __server --port ${port}${hostname ? ` --hostname ${hostname}` : ""}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function nowIso() {
|
|
117
|
+
return new Date().toISOString();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function parsePositiveInt(value, fallback) {
|
|
121
|
+
const n = Number(value);
|
|
122
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function sleep(ms) {
|
|
126
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function readPackageVersion(packageDir) {
|
|
130
|
+
try {
|
|
131
|
+
const installedPkg = JSON.parse(fs.readFileSync(path.join(packageDir, "package.json"), "utf8"));
|
|
132
|
+
return typeof installedPkg.version === "string" ? installedPkg.version : null;
|
|
133
|
+
} catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getInstalledPackageDir() {
|
|
139
|
+
try {
|
|
140
|
+
return path.resolve(path.dirname(fs.realpathSync(getCommandPath())), "..");
|
|
141
|
+
} catch {
|
|
142
|
+
return pkgDir;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function readInstalledVersion() {
|
|
147
|
+
const dirs = [getInstalledPackageDir(), pkgDir];
|
|
148
|
+
for (const dir of dirs) {
|
|
149
|
+
const version = readPackageVersion(dir);
|
|
150
|
+
if (version) return version;
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getRuntimeConnectHost(host) {
|
|
156
|
+
if (!host || host === "0.0.0.0") return "127.0.0.1";
|
|
157
|
+
if (host === "::" || host === "[::]") return "::1";
|
|
158
|
+
return String(host).replace(/^\[(.*)\]$/, "$1");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function canBindPort(listenPort, host) {
|
|
162
|
+
return new Promise((resolve) => {
|
|
163
|
+
const server = net.createServer();
|
|
164
|
+
let settled = false;
|
|
165
|
+
const done = (available) => {
|
|
166
|
+
if (settled) return;
|
|
167
|
+
settled = true;
|
|
168
|
+
resolve(available);
|
|
169
|
+
};
|
|
170
|
+
server.unref();
|
|
171
|
+
server.once("error", () => done(false));
|
|
172
|
+
server.once("listening", () => {
|
|
173
|
+
server.close(() => done(true));
|
|
174
|
+
});
|
|
175
|
+
server.listen(Number(listenPort), host ? String(host) : undefined);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function waitForPortAvailable(listenPort, host, timeoutMs) {
|
|
180
|
+
const startedAt = Date.now();
|
|
181
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
182
|
+
if (await canBindPort(listenPort, host)) return true;
|
|
183
|
+
await sleep(250);
|
|
184
|
+
}
|
|
185
|
+
return canBindPort(listenPort, host);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function fetchRuntimeStatus(internalToken) {
|
|
189
|
+
return new Promise((resolve) => {
|
|
190
|
+
let settled = false;
|
|
191
|
+
const finish = (status) => {
|
|
192
|
+
if (settled) return;
|
|
193
|
+
settled = true;
|
|
194
|
+
resolve(status);
|
|
195
|
+
};
|
|
196
|
+
const req = http.request({
|
|
197
|
+
hostname: getRuntimeConnectHost(hostname),
|
|
198
|
+
port: Number(port),
|
|
199
|
+
path: "/api/internal/runtime",
|
|
200
|
+
method: "GET",
|
|
201
|
+
timeout: INTERNAL_RUNTIME_TIMEOUT_MS,
|
|
202
|
+
headers: {
|
|
203
|
+
"x-annodex-internal-token": internalToken,
|
|
204
|
+
},
|
|
205
|
+
}, (res) => {
|
|
206
|
+
if (res.statusCode !== 200) {
|
|
207
|
+
res.resume();
|
|
208
|
+
finish(null);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
let data = "";
|
|
212
|
+
res.setEncoding("utf8");
|
|
213
|
+
res.on("data", (chunk) => {
|
|
214
|
+
data += chunk;
|
|
215
|
+
if (data.length > 1024 * 1024) req.destroy();
|
|
216
|
+
});
|
|
217
|
+
res.on("end", () => {
|
|
218
|
+
try {
|
|
219
|
+
finish(JSON.parse(data));
|
|
220
|
+
} catch {
|
|
221
|
+
finish(null);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
req.on("error", () => finish(null));
|
|
226
|
+
req.on("timeout", () => {
|
|
227
|
+
req.destroy();
|
|
228
|
+
finish(null);
|
|
229
|
+
});
|
|
230
|
+
req.end();
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function setStableProcessTitle(title) {
|
|
235
|
+
process.title = title;
|
|
236
|
+
try {
|
|
237
|
+
Object.defineProperty(process, "title", {
|
|
238
|
+
configurable: true,
|
|
239
|
+
enumerable: true,
|
|
240
|
+
get: () => title,
|
|
241
|
+
set: () => {},
|
|
242
|
+
});
|
|
243
|
+
} catch {
|
|
244
|
+
const timer = setInterval(() => {
|
|
245
|
+
try { process.title = title; } catch { /* ignore */ }
|
|
246
|
+
}, 500);
|
|
247
|
+
timer.unref();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function readState() {
|
|
252
|
+
try {
|
|
253
|
+
const target = [stateFile, ...legacyStateFiles].find((file) => fs.existsSync(file));
|
|
254
|
+
if (!fs.existsSync(target)) return null;
|
|
255
|
+
return JSON.parse(fs.readFileSync(target, "utf8"));
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function staleStateRemoved() {
|
|
262
|
+
const state = readState();
|
|
263
|
+
if (state && !isPidAlive(state.supervisorPid) && !isPidAlive(state.nextPid)) {
|
|
264
|
+
removeState();
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function writeState(state) {
|
|
271
|
+
ensureAgentDir();
|
|
272
|
+
fs.writeFileSync(stateFile, JSON.stringify({ ...state, updatedAt: nowIso() }, null, 2));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function findListeningPids(listenPort) {
|
|
276
|
+
if (process.platform === "win32") return [];
|
|
277
|
+
const pids = new Set();
|
|
278
|
+
try {
|
|
279
|
+
const result = spawnSync("lsof", [`-tiTCP:${listenPort}`, "-sTCP:LISTEN"], { encoding: "utf8" });
|
|
280
|
+
result.stdout
|
|
281
|
+
.split(/\s+/)
|
|
282
|
+
.map((value) => Number(value))
|
|
283
|
+
.filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid)
|
|
284
|
+
.forEach((pid) => pids.add(pid));
|
|
285
|
+
} catch {
|
|
286
|
+
// Fall through to ss.
|
|
287
|
+
}
|
|
288
|
+
if (pids.size === 0 && process.platform === "linux") {
|
|
289
|
+
try {
|
|
290
|
+
const result = spawnSync("ss", ["-H", "-ltnp", `sport = :${listenPort}`], { encoding: "utf8" });
|
|
291
|
+
const matches = result.stdout.matchAll(/pid=(\d+)/g);
|
|
292
|
+
for (const match of matches) {
|
|
293
|
+
const pid = Number(match[1]);
|
|
294
|
+
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid) pids.add(pid);
|
|
295
|
+
}
|
|
296
|
+
} catch {
|
|
297
|
+
// Ignore lookup failures.
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return [...pids];
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function safeRealpath(targetPath) {
|
|
304
|
+
try {
|
|
305
|
+
return fs.realpathSync(targetPath);
|
|
306
|
+
} catch {
|
|
307
|
+
return targetPath;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function isPathInside(childPath, parentPath) {
|
|
312
|
+
const relative = path.relative(parentPath, childPath);
|
|
313
|
+
return relative === "" || (!!relative && !relative.startsWith("..") && !path.isAbsolute(relative));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function readProcessCmdline(pid) {
|
|
317
|
+
if (!Number.isInteger(pid) || pid <= 0) return "";
|
|
318
|
+
if (process.platform === "linux") {
|
|
319
|
+
try {
|
|
320
|
+
return fs.readFileSync(`/proc/${pid}/cmdline`, "utf8").replace(/\0/g, " ").trim();
|
|
321
|
+
} catch {
|
|
322
|
+
// Fall through to ps.
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
const result = spawnSync("ps", ["-p", String(pid), "-o", "command="], { encoding: "utf8" });
|
|
327
|
+
return result.status === 0 ? result.stdout.trim() : "";
|
|
328
|
+
} catch {
|
|
329
|
+
return "";
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function readProcessCwd(pid) {
|
|
334
|
+
if (!Number.isInteger(pid) || pid <= 0) return "";
|
|
335
|
+
if (process.platform === "linux") {
|
|
336
|
+
try {
|
|
337
|
+
return fs.realpathSync(`/proc/${pid}/cwd`);
|
|
338
|
+
} catch {
|
|
339
|
+
return "";
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (process.platform === "darwin") {
|
|
343
|
+
try {
|
|
344
|
+
const result = spawnSync("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], { encoding: "utf8" });
|
|
345
|
+
if (result.status !== 0) return "";
|
|
346
|
+
const line = result.stdout.split(/\r?\n/).find((value) => value.startsWith("n"));
|
|
347
|
+
return line ? safeRealpath(line.slice(1)) : "";
|
|
348
|
+
} catch {
|
|
349
|
+
return "";
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return "";
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function getProcessSummary(pid) {
|
|
356
|
+
return {
|
|
357
|
+
pid,
|
|
358
|
+
cmdline: readProcessCmdline(pid),
|
|
359
|
+
cwd: readProcessCwd(pid),
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function looksLikeAnnodexProcess(info) {
|
|
364
|
+
const cmdline = info.cmdline || "";
|
|
365
|
+
const cwd = info.cwd || "";
|
|
366
|
+
const realPkgDir = safeRealpath(pkgDir);
|
|
367
|
+
const realCwd = cwd ? safeRealpath(cwd) : "";
|
|
368
|
+
const inAnnodexDir = !!realCwd && isPathInside(realCwd, realPkgDir);
|
|
369
|
+
const commandMentionsAnnodex =
|
|
370
|
+
cmdline.includes("pi-web.js") ||
|
|
371
|
+
cmdline.includes("@seqyuan/annodex") ||
|
|
372
|
+
cmdline.includes("@seqyuan/annovibe") ||
|
|
373
|
+
cmdline.includes("@seqyuan/pidex") ||
|
|
374
|
+
cmdline.includes("/annodex/") ||
|
|
375
|
+
cmdline.includes("/annovibe/") ||
|
|
376
|
+
cmdline.includes("/pidex/") ||
|
|
377
|
+
cmdline.includes("\\annodex\\") ||
|
|
378
|
+
cmdline.includes("\\annovibe\\") ||
|
|
379
|
+
cmdline.includes("\\pidex\\") ||
|
|
380
|
+
cmdline.includes(PROCESS_TITLE);
|
|
381
|
+
const commandMentionsNext =
|
|
382
|
+
cmdline.includes("next-server") ||
|
|
383
|
+
cmdline.includes("next/dist/bin/next") ||
|
|
384
|
+
cmdline.includes("next start");
|
|
385
|
+
|
|
386
|
+
return commandMentionsAnnodex || (inAnnodexDir && commandMentionsNext);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async function stopVerifiedPortListeners(listenPort, quiet = false) {
|
|
390
|
+
const listeningPids = findListeningPids(listenPort);
|
|
391
|
+
if (listeningPids.length === 0) return { found: false, stopped: true, skipped: [] };
|
|
392
|
+
|
|
393
|
+
const verified = [];
|
|
394
|
+
const skipped = [];
|
|
395
|
+
for (const pid of listeningPids) {
|
|
396
|
+
const info = getProcessSummary(pid);
|
|
397
|
+
if (looksLikeAnnodexProcess(info)) {
|
|
398
|
+
verified.push(pid);
|
|
399
|
+
} else {
|
|
400
|
+
skipped.push(info);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (skipped.length > 0) {
|
|
405
|
+
for (const info of skipped) {
|
|
406
|
+
const label = info.cmdline || "unknown command";
|
|
407
|
+
console.error(`annodex stop: port ${listenPort} is used by pid ${info.pid}, but it does not look like annodex; not stopping it.`);
|
|
408
|
+
console.error(`command: ${label}`);
|
|
409
|
+
if (info.cwd) console.error(`cwd: ${info.cwd}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (verified.length === 0) {
|
|
414
|
+
return { found: true, stopped: skipped.length === 0, skipped };
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
let stopped = true;
|
|
418
|
+
for (const pid of verified) {
|
|
419
|
+
stopped = (await terminatePid(pid)) && stopped;
|
|
420
|
+
}
|
|
421
|
+
if (!quiet) {
|
|
422
|
+
console.log(stopped
|
|
423
|
+
? `annodex stop: stopped listener pid${verified.length === 1 ? "" : "s"} ${verified.join(", ")}`
|
|
424
|
+
: `annodex stop: failed to stop listener pid${verified.length === 1 ? "" : "s"} ${verified.join(", ")}`);
|
|
425
|
+
}
|
|
426
|
+
return { found: true, stopped: stopped && skipped.length === 0, skipped };
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function removeState() {
|
|
430
|
+
try { fs.rmSync(stateFile, { force: true }); } catch { /* ignore */ }
|
|
431
|
+
for (const file of legacyStateFiles) {
|
|
432
|
+
try { fs.rmSync(file, { force: true }); } catch { /* ignore */ }
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function isPidAlive(pid) {
|
|
437
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
438
|
+
try {
|
|
439
|
+
process.kill(pid, 0);
|
|
440
|
+
return true;
|
|
441
|
+
} catch (error) {
|
|
442
|
+
return error && error.code === "EPERM";
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function waitForPidExit(pid, timeoutMs) {
|
|
447
|
+
const startedAt = Date.now();
|
|
448
|
+
return new Promise((resolve) => {
|
|
449
|
+
const tick = () => {
|
|
450
|
+
if (!isPidAlive(pid)) {
|
|
451
|
+
resolve(true);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
455
|
+
resolve(false);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
setTimeout(tick, 100);
|
|
459
|
+
};
|
|
460
|
+
tick();
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
async function terminatePid(pid, termTimeoutMs = STOP_TERM_TIMEOUT_MS, killTimeoutMs = STOP_KILL_TIMEOUT_MS) {
|
|
465
|
+
if (!isPidAlive(pid)) return true;
|
|
466
|
+
try {
|
|
467
|
+
process.kill(pid, "SIGTERM");
|
|
468
|
+
} catch {
|
|
469
|
+
return !isPidAlive(pid);
|
|
470
|
+
}
|
|
471
|
+
if (await waitForPidExit(pid, termTimeoutMs)) return true;
|
|
472
|
+
try {
|
|
473
|
+
process.kill(pid, "SIGKILL");
|
|
474
|
+
} catch {
|
|
475
|
+
return !isPidAlive(pid);
|
|
476
|
+
}
|
|
477
|
+
return waitForPidExit(pid, killTimeoutMs);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function renderState(state, json = false) {
|
|
481
|
+
const supervisorAlive = !!state && isPidAlive(state.supervisorPid);
|
|
482
|
+
const nextAlive = !!state && isPidAlive(state.nextPid);
|
|
483
|
+
const status = supervisorAlive ? "running" : nextAlive ? "orphaned" : "stopped";
|
|
484
|
+
const payload = {
|
|
485
|
+
running: supervisorAlive || nextAlive,
|
|
486
|
+
status,
|
|
487
|
+
version: state?.version ?? VERSION,
|
|
488
|
+
url: state?.url ?? getUrl(hostname, port),
|
|
489
|
+
port: state?.port ?? port,
|
|
490
|
+
hostname: state?.hostname ?? hostname,
|
|
491
|
+
supervisorPid: supervisorAlive ? state.supervisorPid : null,
|
|
492
|
+
nextPid: nextAlive ? state.nextPid : null,
|
|
493
|
+
startedAt: supervisorAlive ? state.startedAt ?? null : null,
|
|
494
|
+
restartPending: !!state?.restartPending,
|
|
495
|
+
installedVersion: state?.installedVersion ?? null,
|
|
496
|
+
restartDetectedAt: state?.restartDetectedAt ?? null,
|
|
497
|
+
restartStartedAt: state?.restartStartedAt ?? null,
|
|
498
|
+
logFile,
|
|
499
|
+
stateFile,
|
|
500
|
+
};
|
|
501
|
+
if (json) return JSON.stringify(payload, null, 2);
|
|
502
|
+
if (payload.status === "stopped") {
|
|
503
|
+
return [
|
|
504
|
+
"annodex status: stopped",
|
|
505
|
+
`log: ${payload.logFile}`,
|
|
506
|
+
`state: ${payload.stateFile}`,
|
|
507
|
+
].join("\n");
|
|
508
|
+
}
|
|
509
|
+
return [
|
|
510
|
+
"annodex status: running",
|
|
511
|
+
`url: ${payload.url}`,
|
|
512
|
+
`version: ${payload.version}`,
|
|
513
|
+
`state: ${payload.status}`,
|
|
514
|
+
`supervisor pid: ${payload.supervisorPid ?? "not running"}`,
|
|
515
|
+
`next pid: ${payload.nextPid ?? "unknown"}`,
|
|
516
|
+
`started: ${payload.startedAt ?? "unknown"}`,
|
|
517
|
+
...(payload.restartPending ? [
|
|
518
|
+
`restart: pending${payload.installedVersion ? ` for v${payload.installedVersion}` : ""}`,
|
|
519
|
+
] : []),
|
|
520
|
+
`log: ${payload.logFile}`,
|
|
521
|
+
].join("\n");
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function printRecentLogs(follow = false) {
|
|
525
|
+
ensureAgentDir();
|
|
526
|
+
const targetLogFile = [logFile, ...legacyLogFiles].find((file) => fs.existsSync(file)) ?? logFile;
|
|
527
|
+
if (!fs.existsSync(targetLogFile)) {
|
|
528
|
+
console.log(`annodex logs: no log file yet (${logFile})`);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const content = fs.readFileSync(targetLogFile, "utf8");
|
|
532
|
+
const lines = content.split(/\r?\n/);
|
|
533
|
+
console.log(lines.slice(Math.max(0, lines.length - 200)).join("\n"));
|
|
534
|
+
if (!follow) return;
|
|
535
|
+
const tail = spawn(process.platform === "win32" ? "powershell.exe" : "tail", process.platform === "win32"
|
|
536
|
+
? ["-NoProfile", "-Command", `Get-Content -Path ${JSON.stringify(targetLogFile)} -Wait -Tail 0`]
|
|
537
|
+
: ["-f", targetLogFile], { stdio: "inherit" });
|
|
538
|
+
tail.on("exit", (code) => process.exit(code ?? 0));
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async function stopManagedServer(quiet = false) {
|
|
542
|
+
const state = readState();
|
|
543
|
+
if (!state) {
|
|
544
|
+
const portStop = await stopVerifiedPortListeners(port, quiet);
|
|
545
|
+
if (portStop.found) return portStop.stopped ? 0 : 1;
|
|
546
|
+
if (!quiet) console.log("annodex stop: already stopped");
|
|
547
|
+
return 0;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const supervisorPid = state.supervisorPid;
|
|
551
|
+
const nextPid = state.nextPid;
|
|
552
|
+
let stopped = true;
|
|
553
|
+
if (isPidAlive(supervisorPid)) {
|
|
554
|
+
stopped = await terminatePid(supervisorPid);
|
|
555
|
+
}
|
|
556
|
+
if (nextPid && isPidAlive(nextPid)) {
|
|
557
|
+
stopped = (await terminatePid(nextPid)) && stopped;
|
|
558
|
+
}
|
|
559
|
+
if (stopped) {
|
|
560
|
+
removeState();
|
|
561
|
+
if (!quiet) console.log(`annodex stop: stopped${supervisorPid ? ` pid ${supervisorPid}` : ""}`);
|
|
562
|
+
return 0;
|
|
563
|
+
}
|
|
564
|
+
if (!quiet) console.error(`annodex stop: failed to stop pid ${supervisorPid}`);
|
|
565
|
+
return 1;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
async function startManagedServerWithPort(overridePort, overrideHost) {
|
|
569
|
+
// Temporarily set effective port/hostname for getServerArgs/spawnDetachedServer
|
|
570
|
+
return startManagedServer({ effectivePort: overridePort, effectiveHost: overrideHost });
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
async function startManagedServer({ quiet = false, effectivePort: optPort, effectiveHost: optHost } = {}) {
|
|
574
|
+
seedDefaults();
|
|
575
|
+
await maybeSetupAuth();
|
|
576
|
+
if (!fs.existsSync(nextDir)) {
|
|
577
|
+
console.error("Build artifacts not found. Please report this issue.");
|
|
578
|
+
return 1;
|
|
579
|
+
}
|
|
580
|
+
staleStateRemoved();
|
|
581
|
+
const existing = readState();
|
|
582
|
+
const existingSupervisorAlive = existing && isPidAlive(existing.supervisorPid);
|
|
583
|
+
const existingNextAlive = existing && isPidAlive(existing.nextPid);
|
|
584
|
+
// Preserve port from options > cliArgs > existing state > env > default
|
|
585
|
+
const effectivePort = optPort ?? cliArgs.port ?? existing?.port ?? process.env.PORT ?? "30141";
|
|
586
|
+
const effectiveHost = optHost ?? cliArgs.hostname ?? existing?.hostname ?? process.env.HOSTNAME ?? null;
|
|
587
|
+
if (existingSupervisorAlive) {
|
|
588
|
+
if (!quiet) {
|
|
589
|
+
console.log(`annodex start: already running pid ${existing.supervisorPid}`);
|
|
590
|
+
console.log(`url: ${existing.url ?? getUrl(effectiveHost, effectivePort)}`);
|
|
591
|
+
console.log(`log: ${logFile}`);
|
|
592
|
+
}
|
|
593
|
+
return 0;
|
|
594
|
+
}
|
|
595
|
+
if (existingNextAlive) {
|
|
596
|
+
if (!quiet) console.log(`annodex start: recovering orphaned server pid ${existing.nextPid}`);
|
|
597
|
+
if (!(await terminatePid(existing.nextPid))) {
|
|
598
|
+
if (!quiet) console.error(`annodex start: failed to stop orphaned server pid ${existing.nextPid}`);
|
|
599
|
+
return 1;
|
|
600
|
+
}
|
|
601
|
+
removeState();
|
|
602
|
+
}
|
|
603
|
+
ensureAgentDir();
|
|
604
|
+
const child = spawnDetachedServer({}, effectivePort, effectiveHost);
|
|
605
|
+
if (!child.pid) {
|
|
606
|
+
throw new Error("failed to start annodex server");
|
|
607
|
+
}
|
|
608
|
+
child.unref();
|
|
609
|
+
const state = {
|
|
610
|
+
schemaVersion: 1,
|
|
611
|
+
version: VERSION,
|
|
612
|
+
command: getServerCommand(),
|
|
613
|
+
supervisorPid: child.pid,
|
|
614
|
+
nextPid: null,
|
|
615
|
+
port: String(effectivePort),
|
|
616
|
+
hostname: effectiveHost,
|
|
617
|
+
url: getUrl(effectiveHost, effectivePort),
|
|
618
|
+
logFile,
|
|
619
|
+
stateFile,
|
|
620
|
+
startedAt: nowIso(),
|
|
621
|
+
};
|
|
622
|
+
writeState(state);
|
|
623
|
+
if (!quiet) {
|
|
624
|
+
console.log(`annodex start: pid ${child.pid}`);
|
|
625
|
+
console.log(`url: ${state.url}`);
|
|
626
|
+
console.log(`log: ${logFile}`);
|
|
627
|
+
}
|
|
628
|
+
return 0;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function spawnDetachedServer(extraEnv = {}, overridePort, overrideHost) {
|
|
632
|
+
ensureAgentDir();
|
|
633
|
+
const fd = fs.openSync(logFile, "a");
|
|
634
|
+
const serverArgs = overridePort != null
|
|
635
|
+
? [getCommandPath(), "__server", "--port", String(overridePort), ...(overrideHost ? ["--hostname", overrideHost] : [])]
|
|
636
|
+
: getServerArgs();
|
|
637
|
+
const child = spawn(process.execPath, serverArgs, {
|
|
638
|
+
cwd: fs.existsSync(getInstalledPackageDir()) ? getInstalledPackageDir() : pkgDir,
|
|
639
|
+
detached: true,
|
|
640
|
+
stdio: ["ignore", fd, fd],
|
|
641
|
+
env: {
|
|
642
|
+
...process.env,
|
|
643
|
+
ANNODEX_MANAGED: "1",
|
|
644
|
+
...extraEnv,
|
|
645
|
+
},
|
|
646
|
+
});
|
|
647
|
+
fs.closeSync(fd);
|
|
648
|
+
return child;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if (cliArgs.version) {
|
|
652
|
+
console.log(VERSION);
|
|
653
|
+
process.exit(0);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (cliArgs.help) {
|
|
657
|
+
console.log(`annodex v${VERSION} — Web UI for Codex app-server
|
|
658
|
+
|
|
659
|
+
Usage:
|
|
660
|
+
annodex [options]
|
|
661
|
+
annodex start Start annodex in background
|
|
662
|
+
annodex restart Stop then start annodex in background
|
|
663
|
+
annodex stop Stop background annodex
|
|
664
|
+
annodex status [--json] Show background server status
|
|
665
|
+
annodex logs [-f] Show background server logs
|
|
666
|
+
annodex passwd Change password (or set if none)
|
|
667
|
+
annodex passwd --reset Remove password (disable auth)
|
|
668
|
+
annodex update Update to the latest version
|
|
669
|
+
|
|
670
|
+
Options:
|
|
671
|
+
-p, --port <port> Port to listen on (default: 30141, env: PORT)
|
|
672
|
+
-H, --hostname <host> Hostname to bind to (default: localhost)
|
|
673
|
+
--json Print machine-readable status JSON
|
|
674
|
+
-f, --follow Follow logs
|
|
675
|
+
-v, --version Print version
|
|
676
|
+
-h, --help Show this help
|
|
677
|
+
|
|
678
|
+
Environment:
|
|
679
|
+
PORT Server port
|
|
680
|
+
ANNODEX_PASSWORD Set password on first start
|
|
681
|
+
ANNODEX_AUTO_RESTART Set 0/false/no to disable idle auto-restart after update
|
|
682
|
+
PI_CODING_AGENT_DIR Custom pi agent data directory
|
|
683
|
+
`);
|
|
684
|
+
process.exit(0);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
const firstPos = positionals[0];
|
|
688
|
+
if (firstPos === "status") {
|
|
689
|
+
const json = cliArgs.json;
|
|
690
|
+
staleStateRemoved();
|
|
691
|
+
const state = readState();
|
|
692
|
+
console.log(renderState(state, json));
|
|
693
|
+
process.exit(state && (isPidAlive(state.supervisorPid) || isPidAlive(state.nextPid)) ? 0 : 1);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
if (firstPos === "logs") {
|
|
697
|
+
printRecentLogs(cliArgs.follow);
|
|
698
|
+
if (!cliArgs.follow) process.exit(0);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if (firstPos === "stop") {
|
|
703
|
+
stopManagedServer()
|
|
704
|
+
.then((code) => process.exit(code))
|
|
705
|
+
.catch((error) => {
|
|
706
|
+
console.error(`annodex stop: ${error instanceof Error ? error.message : String(error)}`);
|
|
707
|
+
process.exit(1);
|
|
708
|
+
});
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (firstPos === "start") {
|
|
713
|
+
startManagedServer()
|
|
714
|
+
.then((code) => process.exit(code))
|
|
715
|
+
.catch((error) => {
|
|
716
|
+
console.error(`annodex start: ${error instanceof Error ? error.message : String(error)}`);
|
|
717
|
+
process.exit(1);
|
|
718
|
+
});
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (firstPos === "restart") {
|
|
723
|
+
// Preserve port/hostname from existing state before stopping
|
|
724
|
+
const existingState = readState();
|
|
725
|
+
const restartPort = cliArgs.port ?? existingState?.port ?? port;
|
|
726
|
+
const restartHost = cliArgs.hostname ?? existingState?.hostname ?? hostname;
|
|
727
|
+
stopManagedServer(true).then(async (code) => {
|
|
728
|
+
if (code !== 0) process.exit(code);
|
|
729
|
+
process.exit(await startManagedServerWithPort(restartPort, restartHost));
|
|
730
|
+
}).catch((error) => {
|
|
731
|
+
console.error(`annodex restart: ${error instanceof Error ? error.message : String(error)}`);
|
|
732
|
+
process.exit(1);
|
|
733
|
+
});
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
if (firstPos === "update") {
|
|
738
|
+
console.log(`\n Updating ${PKG_NAME} to latest version...\n`);
|
|
739
|
+
const npmExecPath = process.env.npm_execpath;
|
|
740
|
+
const hasNpmExecPath = npmExecPath && fs.existsSync(npmExecPath);
|
|
741
|
+
const command = hasNpmExecPath ? process.execPath : (process.platform === "win32" ? "npm.cmd" : "npm");
|
|
742
|
+
const args = [
|
|
743
|
+
...(hasNpmExecPath ? [npmExecPath] : []),
|
|
744
|
+
"install", "-g", `${PKG_NAME}@latest`,
|
|
745
|
+
];
|
|
746
|
+
const child = spawn(command, args, { stdio: "inherit" });
|
|
747
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
if (firstPos === "passwd") {
|
|
752
|
+
const reset = positionals[1] === "--reset";
|
|
753
|
+
|
|
754
|
+
if (reset) {
|
|
755
|
+
if (fs.existsSync(authFile)) {
|
|
756
|
+
fs.unlinkSync(authFile);
|
|
757
|
+
console.log(" 🔓 Password removed. Auth disabled.\n");
|
|
758
|
+
} else {
|
|
759
|
+
console.log(" No password configured.\n");
|
|
760
|
+
}
|
|
761
|
+
process.exit(0);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
765
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
766
|
+
(async () => {
|
|
767
|
+
const exists = fs.existsSync(authFile);
|
|
768
|
+
if (exists) {
|
|
769
|
+
console.log("\n Changing password...\n");
|
|
770
|
+
const oldPw = await ask("Current password: ");
|
|
771
|
+
try {
|
|
772
|
+
const cfg = JSON.parse(fs.readFileSync(authFile, "utf8"));
|
|
773
|
+
if (!bcrypt.compareSync(oldPw, cfg.passwordHash)) {
|
|
774
|
+
console.log(" ❌ Incorrect password.\n");
|
|
775
|
+
rl.close();
|
|
776
|
+
process.exit(1);
|
|
777
|
+
}
|
|
778
|
+
} catch { console.log(" ❌ Could not read auth file.\n"); rl.close(); process.exit(1); }
|
|
779
|
+
}
|
|
780
|
+
const pw1 = await ask("New password (empty to disable): ");
|
|
781
|
+
if (!pw1.trim()) {
|
|
782
|
+
if (fs.existsSync(authFile)) fs.unlinkSync(authFile);
|
|
783
|
+
console.log(" 🔓 Auth disabled.\n");
|
|
784
|
+
rl.close();
|
|
785
|
+
process.exit(0);
|
|
786
|
+
}
|
|
787
|
+
const pw2 = await ask("Confirm new password: ");
|
|
788
|
+
if (pw1 !== pw2) {
|
|
789
|
+
console.log(" ❌ Passwords don't match.\n");
|
|
790
|
+
rl.close();
|
|
791
|
+
process.exit(1);
|
|
792
|
+
}
|
|
793
|
+
const hash = bcrypt.hashSync(pw1, 10);
|
|
794
|
+
const dir = path.dirname(authFile);
|
|
795
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
796
|
+
fs.writeFileSync(authFile, JSON.stringify({ passwordHash: hash, enabled: true }, null, 2));
|
|
797
|
+
console.log(exists ? " ✅ Password changed.\n" : " ✅ Password set.\n");
|
|
798
|
+
rl.close();
|
|
799
|
+
process.exit(0);
|
|
800
|
+
})();
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// ── Version check (async, non-blocking) ──
|
|
805
|
+
|
|
806
|
+
function checkVersion() {
|
|
807
|
+
const req = https.get(`https://registry.npmjs.org/${encodeURIComponent(PKG_NAME)}/latest`, { timeout: 5000 }, (res) => {
|
|
808
|
+
let data = "";
|
|
809
|
+
res.on("data", (chunk) => data += chunk);
|
|
810
|
+
res.on("end", () => {
|
|
811
|
+
try {
|
|
812
|
+
const json = JSON.parse(data);
|
|
813
|
+
const latest = json.version;
|
|
814
|
+
if (latest && latest !== VERSION) {
|
|
815
|
+
console.log(`\n ⚡ Update available: ${VERSION} → ${latest}`);
|
|
816
|
+
console.log(` Run: annodex update\n`);
|
|
817
|
+
}
|
|
818
|
+
} catch { /* ignore */ }
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
req.on("error", () => {});
|
|
822
|
+
req.on("timeout", () => req.destroy());
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// ── Normal startup ──
|
|
826
|
+
|
|
827
|
+
function promptPassword() {
|
|
828
|
+
return new Promise((resolve) => {
|
|
829
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
830
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
831
|
+
(async () => {
|
|
832
|
+
console.log("\n🔐 No password set. You can protect annodex with a password.");
|
|
833
|
+
console.log(" Leave empty and press Enter to skip.\n");
|
|
834
|
+
const pw1 = await ask("Enter password: ");
|
|
835
|
+
if (!pw1.trim()) {
|
|
836
|
+
console.log(" Skipped — no password required.\n");
|
|
837
|
+
rl.close();
|
|
838
|
+
resolve(false);
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
const pw2 = await ask("Confirm password: ");
|
|
842
|
+
if (pw1 !== pw2) {
|
|
843
|
+
console.log(" Passwords don't match. Skipping.\n");
|
|
844
|
+
rl.close();
|
|
845
|
+
resolve(false);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
const hash = bcrypt.hashSync(pw1, 10);
|
|
849
|
+
const dir = path.dirname(authFile);
|
|
850
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
851
|
+
fs.writeFileSync(authFile, JSON.stringify({ passwordHash: hash, enabled: true }, null, 2));
|
|
852
|
+
console.log(" ✅ Password set. Restart won't prompt.\n");
|
|
853
|
+
rl.close();
|
|
854
|
+
resolve(true);
|
|
855
|
+
})();
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
async function maybeSetupAuth() {
|
|
860
|
+
if (fs.existsSync(authFile)) return;
|
|
861
|
+
const password = envFirst("ANNODEX_PASSWORD", "ANNOVIBE_PASSWORD", "PIDEX_PASSWORD");
|
|
862
|
+
if (password) {
|
|
863
|
+
const hash = bcrypt.hashSync(password, 10);
|
|
864
|
+
const dir = path.dirname(authFile);
|
|
865
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
866
|
+
fs.writeFileSync(authFile, JSON.stringify({ passwordHash: hash, enabled: true }, null, 2));
|
|
867
|
+
const source = process.env.ANNODEX_PASSWORD ? "ANNODEX_PASSWORD" : process.env.ANNOVIBE_PASSWORD ? "ANNOVIBE_PASSWORD" : "PIDEX_PASSWORD";
|
|
868
|
+
console.log(` 🔐 Password set from ${source} env var.`);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
if (!process.stdin.isTTY) return;
|
|
872
|
+
await promptPassword();
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
function seedDefaults() {
|
|
876
|
+
const defaultSoulSrc = path.join(pkgDir, "lib", "default-SOUL.md");
|
|
877
|
+
const soulDest = path.join(agentDir, "SOUL.md");
|
|
878
|
+
if (!fs.existsSync(soulDest) && fs.existsSync(defaultSoulSrc)) {
|
|
879
|
+
const dir = path.dirname(soulDest);
|
|
880
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
881
|
+
fs.copyFileSync(defaultSoulSrc, soulDest);
|
|
882
|
+
console.log(" 🖖 Default SOUL.md seeded to ~/.config/annodex/SOUL.md");
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
const defaultHarnessSrc = path.join(pkgDir, "lib", "default-HARNESS.md");
|
|
886
|
+
const harnessDest = path.join(agentDir, "HARNESS.md");
|
|
887
|
+
if (!fs.existsSync(harnessDest) && fs.existsSync(defaultHarnessSrc)) {
|
|
888
|
+
const dir = path.dirname(harnessDest);
|
|
889
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
890
|
+
fs.copyFileSync(defaultHarnessSrc, harnessDest);
|
|
891
|
+
console.log(" 📊 Default HARNESS.md seeded to ~/.config/annodex/HARNESS.md");
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// ── Start server ──
|
|
896
|
+
function openBrowser(url) {
|
|
897
|
+
const isWindows = process.platform === "win32";
|
|
898
|
+
const isMac = process.platform === "darwin";
|
|
899
|
+
const openCmd = isWindows ? "start" : isMac ? "open" : "xdg-open";
|
|
900
|
+
const openChild = spawn(openCmd, [url], { shell: isWindows, stdio: "ignore", detached: true });
|
|
901
|
+
openChild.on("error", () => {});
|
|
902
|
+
openChild.unref();
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
function startAutoRestartWatcher({ child, internalToken, writeCurrentState, markRestarting }) {
|
|
906
|
+
if (!AUTO_RESTART_ENABLED) return () => {};
|
|
907
|
+
|
|
908
|
+
let pending = null;
|
|
909
|
+
let idleSince = null;
|
|
910
|
+
let restarting = false;
|
|
911
|
+
let lastWaitLogAt = 0;
|
|
912
|
+
|
|
913
|
+
const poll = async () => {
|
|
914
|
+
if (restarting) return;
|
|
915
|
+
const installedVersion = readInstalledVersion();
|
|
916
|
+
if (!installedVersion || installedVersion === VERSION) {
|
|
917
|
+
if (pending) {
|
|
918
|
+
pending = null;
|
|
919
|
+
idleSince = null;
|
|
920
|
+
writeCurrentState({ restartPending: false, installedVersion: null, restartDetectedAt: null, restartStartedAt: null });
|
|
921
|
+
}
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
if (!pending || pending.installedVersion !== installedVersion) {
|
|
926
|
+
pending = {
|
|
927
|
+
installedVersion,
|
|
928
|
+
detectedAt: nowIso(),
|
|
929
|
+
detectedAtMs: Date.now(),
|
|
930
|
+
};
|
|
931
|
+
idleSince = null;
|
|
932
|
+
lastWaitLogAt = 0;
|
|
933
|
+
console.log(`annodex auto-restart: detected installed version ${installedVersion}; current runtime is ${VERSION}`);
|
|
934
|
+
writeCurrentState({
|
|
935
|
+
restartPending: true,
|
|
936
|
+
installedVersion,
|
|
937
|
+
restartDetectedAt: pending.detectedAt,
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
const status = await fetchRuntimeStatus(internalToken);
|
|
942
|
+
if (!status || typeof status.busy !== "boolean") {
|
|
943
|
+
idleSince = null;
|
|
944
|
+
if (Date.now() - lastWaitLogAt >= 5 * 60_000) {
|
|
945
|
+
lastWaitLogAt = Date.now();
|
|
946
|
+
console.log("annodex auto-restart: waiting for runtime status before restarting");
|
|
947
|
+
}
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
if (status.busy) {
|
|
952
|
+
idleSince = null;
|
|
953
|
+
const waitedMs = Date.now() - pending.detectedAtMs;
|
|
954
|
+
if (Date.now() - lastWaitLogAt >= 5 * 60_000) {
|
|
955
|
+
lastWaitLogAt = Date.now();
|
|
956
|
+
const busyCount = Array.isArray(status.busySessions) ? status.busySessions.length : 0;
|
|
957
|
+
const suffix = waitedMs >= AUTO_RESTART_MAX_WAIT_MS ? "; max wait reached, still waiting for graceful idle" : "";
|
|
958
|
+
console.log(`annodex auto-restart: update pending, waiting for ${busyCount} busy session${busyCount === 1 ? "" : "s"}${suffix}`);
|
|
959
|
+
}
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
idleSince ??= Date.now();
|
|
964
|
+
if (Date.now() - idleSince < AUTO_RESTART_IDLE_GRACE_MS) return;
|
|
965
|
+
|
|
966
|
+
restarting = true;
|
|
967
|
+
let replacement;
|
|
968
|
+
try {
|
|
969
|
+
replacement = spawnDetachedServer({
|
|
970
|
+
ANNODEX_NO_OPEN: "1",
|
|
971
|
+
ANNODEX_WAIT_FOR_PORT: "1",
|
|
972
|
+
ANNOVIBE_NO_OPEN: "1",
|
|
973
|
+
ANNOVIBE_WAIT_FOR_PORT: "1",
|
|
974
|
+
}, port, hostname);
|
|
975
|
+
} catch (error) {
|
|
976
|
+
console.error(`annodex auto-restart: failed to start replacement supervisor: ${error instanceof Error ? error.message : String(error)}`);
|
|
977
|
+
restarting = false;
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
if (!replacement.pid) {
|
|
981
|
+
console.error("annodex auto-restart: failed to start replacement supervisor");
|
|
982
|
+
restarting = false;
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
markRestarting();
|
|
986
|
+
writeCurrentState({
|
|
987
|
+
restartPending: true,
|
|
988
|
+
installedVersion: pending.installedVersion,
|
|
989
|
+
restartDetectedAt: pending.detectedAt,
|
|
990
|
+
restartStartedAt: nowIso(),
|
|
991
|
+
});
|
|
992
|
+
console.log(`annodex auto-restart: installed ${VERSION} -> ${pending.installedVersion}; restarting now`);
|
|
993
|
+
replacement.unref();
|
|
994
|
+
console.log(`annodex auto-restart: replacement supervisor pid ${replacement.pid}`);
|
|
995
|
+
|
|
996
|
+
if (!(await terminatePid(child.pid))) {
|
|
997
|
+
console.error(`annodex auto-restart: failed to stop old next pid ${child.pid}`);
|
|
998
|
+
restarting = false;
|
|
999
|
+
markRestarting(false);
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
process.exit(0);
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
const timer = setInterval(() => {
|
|
1006
|
+
poll().catch((error) => {
|
|
1007
|
+
console.error(`annodex auto-restart: ${error instanceof Error ? error.message : String(error)}`);
|
|
1008
|
+
});
|
|
1009
|
+
}, AUTO_RESTART_POLL_MS);
|
|
1010
|
+
timer.unref();
|
|
1011
|
+
|
|
1012
|
+
poll().catch(() => {});
|
|
1013
|
+
return () => clearInterval(timer);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
async function runServerProcess() {
|
|
1017
|
+
setStableProcessTitle(PROCESS_TITLE);
|
|
1018
|
+
await maybeSetupAuth();
|
|
1019
|
+
if (!fs.existsSync(nextDir)) {
|
|
1020
|
+
console.error("Build artifacts not found. Please report this issue.");
|
|
1021
|
+
process.exit(1);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
checkVersion();
|
|
1025
|
+
|
|
1026
|
+
if (envFirst("ANNODEX_WAIT_FOR_PORT", "ANNOVIBE_WAIT_FOR_PORT") === "1") {
|
|
1027
|
+
const available = await waitForPortAvailable(port, hostname, AUTO_RESTART_WAIT_FOR_PORT_MS);
|
|
1028
|
+
if (!available) {
|
|
1029
|
+
console.error(`annodex server: port ${port} was not released within ${AUTO_RESTART_WAIT_FOR_PORT_MS}ms`);
|
|
1030
|
+
process.exit(1);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
const url = getUrl(hostname, port);
|
|
1035
|
+
const nextArgs = [getCommandPath(), "__next", "--port", String(port)];
|
|
1036
|
+
if (hostname) nextArgs.push("--hostname", hostname);
|
|
1037
|
+
const internalToken = envFirst("ANNODEX_INTERNAL_TOKEN", "ANNOVIBE_INTERNAL_TOKEN") || randomBytes(24).toString("hex");
|
|
1038
|
+
|
|
1039
|
+
const child = spawn(process.execPath, nextArgs, {
|
|
1040
|
+
cwd: pkgDir,
|
|
1041
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1042
|
+
env: {
|
|
1043
|
+
...process.env,
|
|
1044
|
+
ANNODEX_INTERNAL_TOKEN: internalToken,
|
|
1045
|
+
ANNOVIBE_INTERNAL_TOKEN: internalToken,
|
|
1046
|
+
ANNODEX_SUPERVISOR_PID: String(process.pid),
|
|
1047
|
+
ANNODEX_NEXT_WRAPPER: "1",
|
|
1048
|
+
},
|
|
1049
|
+
});
|
|
1050
|
+
let restarting = false;
|
|
1051
|
+
|
|
1052
|
+
const writeCurrentState = (patch = {}) => {
|
|
1053
|
+
const current = readState() ?? {};
|
|
1054
|
+
writeState({
|
|
1055
|
+
schemaVersion: 1,
|
|
1056
|
+
version: VERSION,
|
|
1057
|
+
command: getServerCommand(),
|
|
1058
|
+
supervisorPid: process.pid,
|
|
1059
|
+
nextPid: child.pid ?? null,
|
|
1060
|
+
port: String(port),
|
|
1061
|
+
hostname,
|
|
1062
|
+
url,
|
|
1063
|
+
logFile,
|
|
1064
|
+
stateFile,
|
|
1065
|
+
startedAt: current.startedAt ?? nowIso(),
|
|
1066
|
+
...patch,
|
|
1067
|
+
});
|
|
1068
|
+
};
|
|
1069
|
+
|
|
1070
|
+
writeCurrentState();
|
|
1071
|
+
const stopAutoRestartWatcher = startAutoRestartWatcher({
|
|
1072
|
+
child,
|
|
1073
|
+
internalToken,
|
|
1074
|
+
writeCurrentState,
|
|
1075
|
+
markRestarting: (value = true) => { restarting = value; },
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
let browserOpened = false;
|
|
1079
|
+
child.stdout.on("data", (chunk) => {
|
|
1080
|
+
const text = chunk.toString();
|
|
1081
|
+
process.stdout.write(text);
|
|
1082
|
+
if (!browserOpened && text.includes("Ready")) {
|
|
1083
|
+
browserOpened = true;
|
|
1084
|
+
if (envFirst("ANNODEX_NO_OPEN", "ANNOVIBE_NO_OPEN") !== "1") openBrowser(url);
|
|
1085
|
+
console.log(`\n annodex running at ${url}\n`);
|
|
1086
|
+
writeCurrentState({ readyAt: nowIso() });
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
child.stderr.on("data", (chunk) => process.stderr.write(chunk));
|
|
1090
|
+
|
|
1091
|
+
const shutdown = async () => {
|
|
1092
|
+
stopAutoRestartWatcher();
|
|
1093
|
+
await terminatePid(child.pid);
|
|
1094
|
+
if (!restarting) removeState();
|
|
1095
|
+
process.exit(0);
|
|
1096
|
+
};
|
|
1097
|
+
process.on("SIGTERM", () => { void shutdown(); });
|
|
1098
|
+
process.on("SIGINT", () => { void shutdown(); });
|
|
1099
|
+
|
|
1100
|
+
child.on("exit", (code) => {
|
|
1101
|
+
stopAutoRestartWatcher();
|
|
1102
|
+
if (!restarting) removeState();
|
|
1103
|
+
process.exit(code ?? 0);
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
function runNextProcess() {
|
|
1108
|
+
setStableProcessTitle(NEXT_PROCESS_TITLE);
|
|
1109
|
+
if (!fs.existsSync(nextDir)) {
|
|
1110
|
+
console.error("Build artifacts not found. Please report this issue.");
|
|
1111
|
+
process.exit(1);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
const nextArgs = ["start", "-p", String(port)];
|
|
1115
|
+
if (hostname) nextArgs.push("-H", String(hostname));
|
|
1116
|
+
process.argv = [process.execPath, nextBin, ...nextArgs];
|
|
1117
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1118
|
+
require(nextBin);
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
if (firstPos === "__server") {
|
|
1122
|
+
runServerProcess().catch((error) => {
|
|
1123
|
+
console.error(`annodex server: ${error instanceof Error ? error.message : String(error)}`);
|
|
1124
|
+
process.exit(1);
|
|
1125
|
+
});
|
|
1126
|
+
} else if (firstPos === "__next") {
|
|
1127
|
+
try {
|
|
1128
|
+
runNextProcess();
|
|
1129
|
+
} catch (error) {
|
|
1130
|
+
console.error(`annodex next: ${error instanceof Error ? error.message : String(error)}`);
|
|
1131
|
+
process.exit(1);
|
|
1132
|
+
}
|
|
1133
|
+
} else {
|
|
1134
|
+
startManagedServer()
|
|
1135
|
+
.then((code) => process.exit(code))
|
|
1136
|
+
.catch((error) => {
|
|
1137
|
+
console.error(`annodex start: ${error instanceof Error ? error.message : String(error)}`);
|
|
1138
|
+
process.exit(1);
|
|
1139
|
+
});
|
|
1140
|
+
}
|