axonrouter 2.0.2 → 2.0.4
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/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/analytics/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/basic-chat/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/caveman/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/caveman/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/combos/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/console-log/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/intelligence/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/intelligence/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/mcp/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/mcp/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/media-providers/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/media-providers/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/mitm/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/morph/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/morph/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/opencode/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/opencode/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/profile/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/new/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/proxy-pools/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/quota/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/settings/pricing/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/skills/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/translator/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/usage/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/callback/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/callback.html +1 -1
- package/.next/standalone/.next/server/app/callback.rsc +3 -3
- package/.next/standalone/.next/server/app/callback.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/callback.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/callback.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/callback.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/callback.segments/callback.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/analytics.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/analytics.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard/analytics/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard/analytics.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/analytics.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/basic-chat.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/basic-chat.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/caveman.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/caveman.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/!KGRhc2hib2FyZCk/dashboard/caveman/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/!KGRhc2hib2FyZCk/dashboard/caveman.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/caveman.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/cli-tools.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/cli-tools.rsc +7 -7
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/combos.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/combos.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/endpoint.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/endpoint.rsc +7 -7
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/intelligence.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/intelligence.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/!KGRhc2hib2FyZCk/dashboard/intelligence/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/!KGRhc2hib2FyZCk/dashboard/intelligence.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/intelligence.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/mcp.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/mcp.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/!KGRhc2hib2FyZCk/dashboard/mcp/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/!KGRhc2hib2FyZCk/dashboard/mcp.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/mcp.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/media-providers.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/media-providers.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/media-providers.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/mitm.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/mitm.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/morph.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/morph.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/morph.segments/!KGRhc2hib2FyZCk/dashboard/morph/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/morph.segments/!KGRhc2hib2FyZCk/dashboard/morph.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/morph.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/morph.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/morph.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/morph.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/morph.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/morph.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/opencode.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/opencode.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/!KGRhc2hib2FyZCk/dashboard/opencode/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/!KGRhc2hib2FyZCk/dashboard/opencode.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/opencode.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/profile.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/profile.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers/new.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers/new.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/quota.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/quota.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/!KGRhc2hib2FyZCk/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/!KGRhc2hib2FyZCk/dashboard/settings/pricing.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/!KGRhc2hib2FyZCk/dashboard/settings.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/settings.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/settings.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/settings.segments/!KGRhc2hib2FyZCk/dashboard/settings/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/settings.segments/!KGRhc2hib2FyZCk/dashboard/settings.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/settings.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/settings.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/skills.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/skills.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/skills.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/skills.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/skills.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/skills.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/translator.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/translator.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/usage.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/usage.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_full.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard.html +1 -1
- package/.next/standalone/.next/server/app/dashboard.rsc +7 -7
- package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/dashboard.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/dashboard.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/landing/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/landing.html +1 -1
- package/.next/standalone/.next/server/app/landing.rsc +3 -3
- package/.next/standalone/.next/server/app/landing.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/landing.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/landing.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/landing.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/landing.segments/landing.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login.html +1 -1
- package/.next/standalone/.next/server/app/login.rsc +3 -3
- package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.mzodm._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__003scm0._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__01kq~.r._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__03sw1c3._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0brgjhf._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d~p0cq._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0h9.ugv._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0i8ubss._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0k2~rdk._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0k6jln3._.js +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0m.0h8z._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0n~_i6e._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o_0bxa._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0uvu.gs._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zbooww._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0743~zr._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0h~0zar._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0k_a0xx.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0o8sjwu.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0tqpghm.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_12p6yih.js +5 -5
- package/.next/standalone/.next/server/chunks/ssr/_0-o1.gf._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0-~8uap._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_13vwxhk._.js → _03~l39c._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_04w48i.._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0_hztrw._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0bquxrm._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0k060hw._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0p0d9p4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0p_8t2a._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0y_u_c_._.js +7 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/WorkerProxy/package-lock.json +3570 -0
- package/.next/standalone/WorkerProxy/package.json +22 -0
- package/.next/standalone/WorkerProxy/tsconfig.json +20 -0
- package/.next/standalone/package-lock.json +2 -2
- package/.next/standalone/package.json +3 -2
- package/.next/static/chunks/{0-7g8~~9az0a9.js → 0-8mpnlo8y_tj.js} +1 -1
- package/.next/static/chunks/{09zlsx5qsaeuo.js → 00j87-lc_wvtd.js} +1 -1
- package/.next/static/chunks/08hgd_~o140~6.js +1 -0
- package/.next/static/chunks/093sb5s6tg.d~.js +7 -0
- package/.next/static/chunks/0hf--lbch~.di.js +1 -0
- package/.next/static/chunks/0o3xjtrgx~i2u.js +1 -0
- package/.next/static/chunks/0r_8gbx840jol.js +1 -0
- package/.next/static/chunks/0s~jr3m--sfo2.js +5 -0
- package/.next/static/chunks/0woj8_9_5ws~k.css +1 -0
- package/.next/static/chunks/0~t7g-h-wdi67.js +1 -0
- package/installer.sh +211 -0
- package/package.json +3 -2
- package/scripts/service.js +386 -74
- package/scripts/start.js +23 -1
- package/src/app/login/page.tsx +39 -314
- package/.next/standalone/.next/server/chunks/ssr/_00f6536._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_01hq7xj._.js +0 -7
- package/.next/standalone/.next/server/chunks/ssr/_0c9x38a._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0fikbv4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0fk4yvh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0frtcm3._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0khqaqv._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0x0xx9p._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_13u7lt-._.js +0 -3
- package/.next/static/chunks/0-6gya.tj0dk7.js +0 -1
- package/.next/static/chunks/04quk80rrt07~.js +0 -1
- package/.next/static/chunks/0eu47j24g2bzm.js +0 -5
- package/.next/static/chunks/0iv_qp-wgtx-_.css +0 -1
- package/.next/static/chunks/0jyn0615kxxi1.js +0 -1
- package/.next/static/chunks/0peqcn6~om0vp.js +0 -1
- package/.next/static/chunks/0vqox~1257tth.js +0 -1
- package/.next/static/chunks/0x871_qyqh.y4.js +0 -1
- package/.next/static/chunks/15p_plajhlg_e.js +0 -7
- /package/.next/static/{olzWK3KCh9LlwHyWUO_bm → JwKavHa5OgD3g5HXE6pag}/_buildManifest.js +0 -0
- /package/.next/static/{olzWK3KCh9LlwHyWUO_bm → JwKavHa5OgD3g5HXE6pag}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{olzWK3KCh9LlwHyWUO_bm → JwKavHa5OgD3g5HXE6pag}/_ssgManifest.js +0 -0
package/scripts/service.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// IMPORTANT: Never chown the axonrouter package directory to root.
|
|
3
|
+
// This breaks native modules like better-sqlite3.
|
|
2
4
|
|
|
3
5
|
import { execSync, spawnSync } from "node:child_process";
|
|
4
6
|
import fs from "node:fs";
|
|
7
|
+
import os from "node:os";
|
|
5
8
|
import path from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
6
10
|
|
|
7
11
|
const SERVICE_NAME = "axonrouter";
|
|
8
12
|
const SYSTEMD_UNIT_PATH = `/etc/systemd/system/${SERVICE_NAME}.service`;
|
|
@@ -10,6 +14,9 @@ const INITD_SCRIPT_PATH = `/etc/init.d/${SERVICE_NAME}`;
|
|
|
10
14
|
const PID_FILE = `/var/run/${SERVICE_NAME}.pid`;
|
|
11
15
|
const DEFAULT_PORT = 12711;
|
|
12
16
|
|
|
17
|
+
const USER_SYSTEMD_DIR = path.join(os.homedir(), ".config", "systemd", "user");
|
|
18
|
+
const USER_UNIT_PATH = path.join(USER_SYSTEMD_DIR, `${SERVICE_NAME}.service`);
|
|
19
|
+
|
|
13
20
|
/**
|
|
14
21
|
* Check if the current process is running as root (uid 0).
|
|
15
22
|
*/
|
|
@@ -17,17 +24,6 @@ export function isRoot() {
|
|
|
17
24
|
return process.getuid() === 0;
|
|
18
25
|
}
|
|
19
26
|
|
|
20
|
-
/**
|
|
21
|
-
* Require root privileges. Prints error and exits if not root.
|
|
22
|
-
*/
|
|
23
|
-
export function requireRoot() {
|
|
24
|
-
if (!isRoot()) {
|
|
25
|
-
console.error("\x1b[31m[AxonRouter] Error: Service management requires root privileges.\x1b[0m");
|
|
26
|
-
console.error("\x1b[33mPlease run with sudo: sudo axonrouter install-service\x1b[0m");
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
27
|
/**
|
|
32
28
|
* Run a command with sudo if not already root.
|
|
33
29
|
* Prompts for password interactively when needed.
|
|
@@ -63,15 +59,13 @@ export function detectInitSystem() {
|
|
|
63
59
|
}
|
|
64
60
|
|
|
65
61
|
/**
|
|
66
|
-
* Get the path to the axonrouter binary
|
|
62
|
+
* Get the path to the axonrouter binary resolved from import.meta.url.
|
|
63
|
+
* This avoids relying on 'which axonrouter' which fails under sudo or nvm.
|
|
67
64
|
*/
|
|
68
65
|
export function getExecPath() {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// Fallback to the current process argv
|
|
73
|
-
return process.argv[1] || "/usr/local/bin/axonrouter";
|
|
74
|
-
}
|
|
66
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
67
|
+
const __dirname = path.dirname(__filename);
|
|
68
|
+
return path.resolve(__dirname, "..", "bin", "axonrouter.js");
|
|
75
69
|
}
|
|
76
70
|
|
|
77
71
|
/**
|
|
@@ -83,41 +77,171 @@ export function getNodePath() {
|
|
|
83
77
|
return process.execPath;
|
|
84
78
|
}
|
|
85
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Resolve the home directory for a given user.
|
|
82
|
+
* When SUDO_USER is set, tries /etc/passwd lookup, then falls back to /home/<user>.
|
|
83
|
+
* For root, returns /root. Otherwise falls back to os.homedir().
|
|
84
|
+
*/
|
|
85
|
+
export function getInstallingUserHome(user) {
|
|
86
|
+
if (user === "root") {
|
|
87
|
+
return "/root";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Try to read from /etc/passwd
|
|
91
|
+
try {
|
|
92
|
+
const passwd = fs.readFileSync("/etc/passwd", "utf-8");
|
|
93
|
+
const lines = passwd.split("\n");
|
|
94
|
+
for (const line of lines) {
|
|
95
|
+
const fields = line.split(":");
|
|
96
|
+
if (fields[0] === user && fields[5]) {
|
|
97
|
+
return fields[5];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} catch {
|
|
101
|
+
// /etc/passwd not readable, fall through
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Fall back to /home/<user> if SUDO_USER is set
|
|
105
|
+
if (process.env.SUDO_USER) {
|
|
106
|
+
return `/home/${user}`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return os.homedir();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Detect the real (non-root) user who invoked the install command.
|
|
114
|
+
* When run via sudo, reads SUDO_USER and SUDO_GID for the original user.
|
|
115
|
+
* Otherwise uses os.userInfo() for the current user.
|
|
116
|
+
* Returns { user, group, home }.
|
|
117
|
+
*/
|
|
118
|
+
export function getInstallingUser() {
|
|
119
|
+
const sudoUser = process.env.SUDO_USER;
|
|
120
|
+
|
|
121
|
+
if (sudoUser) {
|
|
122
|
+
let group = process.env.SUDO_GID || String(os.userInfo().gid);
|
|
123
|
+
// Try to resolve group name from GID via /etc/group
|
|
124
|
+
try {
|
|
125
|
+
const groupFile = fs.readFileSync("/etc/group", "utf-8");
|
|
126
|
+
const lines = groupFile.split("\n");
|
|
127
|
+
for (const line of lines) {
|
|
128
|
+
const fields = line.split(":");
|
|
129
|
+
if (fields[2] === group) {
|
|
130
|
+
group = fields[0];
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
// If we can't resolve the group name, use the username as group
|
|
136
|
+
group = sudoUser;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// If group is still numeric (GID didn't resolve), fall back to username
|
|
140
|
+
if (/^\d+$/.test(group)) {
|
|
141
|
+
group = sudoUser;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const home = getInstallingUserHome(sudoUser);
|
|
145
|
+
return { user: sudoUser, group, home };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const info = os.userInfo();
|
|
149
|
+
const user = info.username;
|
|
150
|
+
let group = String(info.gid);
|
|
151
|
+
|
|
152
|
+
// Try to resolve group name from GID via /etc/group
|
|
153
|
+
try {
|
|
154
|
+
const groupFile = fs.readFileSync("/etc/group", "utf-8");
|
|
155
|
+
const lines = groupFile.split("\n");
|
|
156
|
+
for (const line of lines) {
|
|
157
|
+
const fields = line.split(":");
|
|
158
|
+
if (fields[2] === group) {
|
|
159
|
+
group = fields[0];
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} catch {
|
|
164
|
+
// Fall back to username as group
|
|
165
|
+
group = user;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// If group is still numeric (GID didn't resolve), fall back to username
|
|
169
|
+
if (/^\d+$/.test(group)) {
|
|
170
|
+
group = user;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const home = getInstallingUserHome(user);
|
|
174
|
+
return { user, group, home };
|
|
175
|
+
}
|
|
176
|
+
|
|
86
177
|
/**
|
|
87
178
|
* Generate systemd unit file content.
|
|
88
179
|
* Uses absolute node path + script path to avoid shebang/PATH issues under systemd.
|
|
180
|
+
* Accepts an optional userInfo parameter to avoid repeated getInstallingUser() calls.
|
|
181
|
+
* When userMode is true, omits User=/Group= and uses WantedBy=default.target.
|
|
89
182
|
*/
|
|
90
|
-
export function generateSystemdUnit(execPath) {
|
|
183
|
+
export function generateSystemdUnit(execPath, userInfo, options = {}) {
|
|
91
184
|
const nodePath = getNodePath();
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
StartLimitIntervalSec=300
|
|
96
|
-
StartLimitBurst=5
|
|
185
|
+
const { user, group, home } = userInfo || getInstallingUser();
|
|
186
|
+
const workingDirectory = path.resolve(path.dirname(execPath), "..");
|
|
187
|
+
const userMode = options.userMode || false;
|
|
97
188
|
|
|
98
|
-
|
|
189
|
+
let serviceSection;
|
|
190
|
+
if (userMode) {
|
|
191
|
+
serviceSection = `[Service]
|
|
99
192
|
Type=simple
|
|
193
|
+
WorkingDirectory=${workingDirectory}
|
|
100
194
|
ExecStart=${nodePath} ${execPath}
|
|
101
195
|
Restart=always
|
|
102
196
|
RestartSec=5
|
|
103
197
|
Environment=NODE_ENV=production
|
|
104
198
|
Environment=PORT=${DEFAULT_PORT}
|
|
199
|
+
Environment=HOME=${home}
|
|
105
200
|
# Graceful shutdown timeout
|
|
106
201
|
TimeoutStopSec=30
|
|
107
202
|
# Kill remaining child processes (cloudflared, tailscaled) on stop
|
|
108
|
-
KillMode=control-group
|
|
203
|
+
KillMode=control-group`;
|
|
204
|
+
} else {
|
|
205
|
+
serviceSection = `[Service]
|
|
206
|
+
Type=simple
|
|
207
|
+
User=${user}
|
|
208
|
+
Group=${group}
|
|
209
|
+
WorkingDirectory=${workingDirectory}
|
|
210
|
+
ExecStart=${nodePath} ${execPath}
|
|
211
|
+
Restart=always
|
|
212
|
+
RestartSec=5
|
|
213
|
+
Environment=NODE_ENV=production
|
|
214
|
+
Environment=PORT=${DEFAULT_PORT}
|
|
215
|
+
Environment=HOME=${home}
|
|
216
|
+
# Graceful shutdown timeout
|
|
217
|
+
TimeoutStopSec=30
|
|
218
|
+
# Kill remaining child processes (cloudflared, tailscaled) on stop
|
|
219
|
+
KillMode=control-group`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const wantedBy = userMode ? "default.target" : "multi-user.target";
|
|
223
|
+
|
|
224
|
+
return `[Unit]
|
|
225
|
+
Description=AxonRouter AI Router
|
|
226
|
+
After=network.target
|
|
227
|
+
StartLimitIntervalSec=300
|
|
228
|
+
StartLimitBurst=5
|
|
229
|
+
|
|
230
|
+
${serviceSection}
|
|
109
231
|
|
|
110
232
|
[Install]
|
|
111
|
-
WantedBy
|
|
233
|
+
WantedBy=${wantedBy}
|
|
112
234
|
`;
|
|
113
235
|
}
|
|
114
236
|
|
|
115
237
|
/**
|
|
116
238
|
* Generate init.d script content (LSB format).
|
|
117
239
|
* Uses absolute node path to avoid PATH issues in init environment.
|
|
240
|
+
* Accepts an optional userInfo parameter to avoid repeated getInstallingUser() calls.
|
|
118
241
|
*/
|
|
119
|
-
export function generateInitdScript(execPath) {
|
|
242
|
+
export function generateInitdScript(execPath, userInfo) {
|
|
120
243
|
const nodePath = getNodePath();
|
|
244
|
+
const { user, group, home } = userInfo || getInstallingUser();
|
|
121
245
|
return `#!/bin/sh
|
|
122
246
|
### BEGIN INIT INFO
|
|
123
247
|
# Provides: ${SERVICE_NAME}
|
|
@@ -134,21 +258,24 @@ DAEMON="${execPath}"
|
|
|
134
258
|
PIDFILE="${PID_FILE}"
|
|
135
259
|
NAME="${SERVICE_NAME}"
|
|
136
260
|
LOG_FILE="/var/log/${SERVICE_NAME}.log"
|
|
261
|
+
USER="${user}"
|
|
262
|
+
GROUP="${group}"
|
|
137
263
|
export NODE_ENV=production
|
|
138
264
|
export PORT=${DEFAULT_PORT}
|
|
265
|
+
export HOME=${home}
|
|
139
266
|
|
|
140
267
|
start() {
|
|
141
268
|
if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
|
|
142
269
|
echo "$NAME is already running."
|
|
143
270
|
return 1
|
|
144
271
|
fi
|
|
145
|
-
echo "Starting $NAME..."
|
|
272
|
+
echo "Starting $NAME as user $USER..."
|
|
146
273
|
# Start with auto-respawn: restart up to 10 times with 5s delay if process exits
|
|
147
274
|
(
|
|
148
275
|
RESTART_COUNT=0
|
|
149
276
|
MAX_RESTARTS=10
|
|
150
277
|
while [ $RESTART_COUNT -lt $MAX_RESTARTS ]; do
|
|
151
|
-
"$
|
|
278
|
+
su - "$USER" -c "HOME='${home}' NODE_ENV=production PORT=${DEFAULT_PORT} '${nodePath}' '${execPath}'" >> "$LOG_FILE" 2>&1
|
|
152
279
|
EXIT_CODE=$?
|
|
153
280
|
if [ $EXIT_CODE -eq 0 ]; then
|
|
154
281
|
break
|
|
@@ -204,36 +331,97 @@ exit 0
|
|
|
204
331
|
`;
|
|
205
332
|
}
|
|
206
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Check if the user session bus is available for systemctl --user commands.
|
|
336
|
+
* Returns true if the session bus is accessible, false otherwise.
|
|
337
|
+
*/
|
|
338
|
+
export function isUserSessionAvailable() {
|
|
339
|
+
if (process.env.XDG_RUNTIME_DIR || process.env.DBUS_SESSION_BUS_ADDRESS) {
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
// Try running systemctl --user as a final check
|
|
343
|
+
try {
|
|
344
|
+
execSync("systemctl --user --no-pager status", { stdio: "ignore" });
|
|
345
|
+
return true;
|
|
346
|
+
} catch {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Get the user-level unit path for a specific user.
|
|
353
|
+
* When running as root with SUDO_USER set, resolves to that user's home.
|
|
354
|
+
*/
|
|
355
|
+
export function getUserUnitPath(targetUser) {
|
|
356
|
+
if (targetUser) {
|
|
357
|
+
const home = getInstallingUserHome(targetUser);
|
|
358
|
+
return path.join(home, ".config", "systemd", "user", `${SERVICE_NAME}.service`);
|
|
359
|
+
}
|
|
360
|
+
return USER_UNIT_PATH;
|
|
361
|
+
}
|
|
362
|
+
|
|
207
363
|
/**
|
|
208
364
|
* Install the service (systemd or init.d).
|
|
209
|
-
*
|
|
365
|
+
* When running as non-root with systemd, installs a user-level service.
|
|
366
|
+
* When running as root with systemd, installs a system-level service.
|
|
367
|
+
* For init.d, always uses sudo (no user-level support).
|
|
210
368
|
*/
|
|
211
369
|
export function installService() {
|
|
212
370
|
const initSystem = detectInitSystem();
|
|
213
371
|
const execPath = getExecPath();
|
|
372
|
+
const { user, group } = getInstallingUser();
|
|
214
373
|
|
|
215
374
|
console.log(`[AxonRouter] Detected init system: ${initSystem}`);
|
|
216
375
|
console.log(`[AxonRouter] Executable path: ${execPath}`);
|
|
376
|
+
console.log(`[AxonRouter] Service will run as user: ${user} (group: ${group})`);
|
|
377
|
+
|
|
378
|
+
const userInfo = { user, group, home: getInstallingUserHome(user) };
|
|
217
379
|
|
|
218
380
|
if (initSystem === "systemd") {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
381
|
+
if (isRoot()) {
|
|
382
|
+
// System-level service installation (existing behavior)
|
|
383
|
+
const unitContent = generateSystemdUnit(execPath, userInfo);
|
|
384
|
+
const child = spawnSync("sudo", ["tee", SYSTEMD_UNIT_PATH], {
|
|
385
|
+
input: unitContent,
|
|
386
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
387
|
+
});
|
|
388
|
+
if (child.status !== 0) {
|
|
389
|
+
console.error("[AxonRouter] Failed to write service file. Sudo access required.");
|
|
390
|
+
process.exit(1);
|
|
391
|
+
}
|
|
392
|
+
console.log(`[AxonRouter] Service file written to ${SYSTEMD_UNIT_PATH}`);
|
|
393
|
+
|
|
394
|
+
runWithSudo("systemctl daemon-reload");
|
|
395
|
+
runWithSudo(`systemctl enable ${SERVICE_NAME}`);
|
|
396
|
+
runWithSudo(`systemctl start ${SERVICE_NAME}`);
|
|
397
|
+
console.log(`[AxonRouter] System-level service installed, enabled, and started.`);
|
|
398
|
+
} else {
|
|
399
|
+
// User-level service installation (no sudo needed)
|
|
400
|
+
if (!isUserSessionAvailable()) {
|
|
401
|
+
console.error(`[AxonRouter] ERROR: User session bus is not available.`);
|
|
402
|
+
console.error(`[AxonRouter] systemctl --user requires an active user session or lingering enabled.`);
|
|
403
|
+
console.error(`[AxonRouter] To fix this, run: sudo loginctl enable-linger ${user}`);
|
|
404
|
+
console.error(`[AxonRouter] Then log out and back in, or reboot.`);
|
|
405
|
+
process.exit(1);
|
|
406
|
+
}
|
|
230
407
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
408
|
+
const unitContent = generateSystemdUnit(execPath, userInfo, { userMode: true });
|
|
409
|
+
|
|
410
|
+
fs.mkdirSync(USER_SYSTEMD_DIR, { recursive: true });
|
|
411
|
+
fs.writeFileSync(USER_UNIT_PATH, unitContent);
|
|
412
|
+
console.log(`[AxonRouter] Service file written to ${USER_UNIT_PATH}`);
|
|
413
|
+
|
|
414
|
+
execSync("systemctl --user daemon-reload", { stdio: "inherit" });
|
|
415
|
+
execSync(`systemctl --user enable ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
416
|
+
execSync(`systemctl --user start ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
417
|
+
|
|
418
|
+
console.log(`[AxonRouter] User-level service installed and started.`);
|
|
419
|
+
console.log(`[AxonRouter] To start at boot without login, run: sudo loginctl enable-linger ${user}`);
|
|
420
|
+
}
|
|
235
421
|
} else {
|
|
236
|
-
|
|
422
|
+
// init.d has no user-level support, requires sudo
|
|
423
|
+
console.log(`[AxonRouter] init.d does not support user-level services; sudo is required.`);
|
|
424
|
+
const scriptContent = generateInitdScript(execPath, userInfo);
|
|
237
425
|
const child = spawnSync("sudo", ["tee", INITD_SCRIPT_PATH], {
|
|
238
426
|
input: scriptContent,
|
|
239
427
|
stdio: ["pipe", "pipe", "inherit"],
|
|
@@ -262,6 +450,8 @@ export function installService() {
|
|
|
262
450
|
|
|
263
451
|
/**
|
|
264
452
|
* Uninstall the service (stop, disable, remove).
|
|
453
|
+
* Detects whether a user-level or system-level service is installed.
|
|
454
|
+
* When running as root, checks if SUDO_USER has a user-level unit.
|
|
265
455
|
*/
|
|
266
456
|
export function uninstallService() {
|
|
267
457
|
const initSystem = detectInitSystem();
|
|
@@ -269,24 +459,82 @@ export function uninstallService() {
|
|
|
269
459
|
console.log(`[AxonRouter] Detected init system: ${initSystem}`);
|
|
270
460
|
|
|
271
461
|
if (initSystem === "systemd") {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
462
|
+
// When running as root with SUDO_USER, check that user's unit path too
|
|
463
|
+
const sudoUser = process.env.SUDO_USER;
|
|
464
|
+
const effectiveUserUnitPath = (isRoot() && sudoUser)
|
|
465
|
+
? getUserUnitPath(sudoUser)
|
|
466
|
+
: USER_UNIT_PATH;
|
|
467
|
+
|
|
468
|
+
const userLevelExists = fs.existsSync(effectiveUserUnitPath);
|
|
469
|
+
const systemLevelExists = fs.existsSync(SYSTEMD_UNIT_PATH);
|
|
470
|
+
|
|
471
|
+
if (userLevelExists && !isRoot()) {
|
|
472
|
+
// Uninstall user-level service (current user)
|
|
473
|
+
try {
|
|
474
|
+
execSync(`systemctl --user stop ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
475
|
+
} catch {
|
|
476
|
+
// Service might not be running
|
|
477
|
+
}
|
|
478
|
+
try {
|
|
479
|
+
execSync(`systemctl --user disable ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
480
|
+
} catch {
|
|
481
|
+
// Service might not be enabled
|
|
482
|
+
}
|
|
483
|
+
try {
|
|
484
|
+
fs.unlinkSync(USER_UNIT_PATH);
|
|
485
|
+
console.log(`[AxonRouter] Removed ${USER_UNIT_PATH}`);
|
|
486
|
+
} catch {
|
|
487
|
+
// File might not exist
|
|
488
|
+
}
|
|
489
|
+
execSync("systemctl --user daemon-reload", { stdio: "inherit" });
|
|
490
|
+
console.log(`[AxonRouter] User-level service uninstalled.`);
|
|
491
|
+
} else if (userLevelExists && isRoot() && sudoUser) {
|
|
492
|
+
// Root is uninstalling a user-level service owned by SUDO_USER
|
|
493
|
+
try {
|
|
494
|
+
execSync(`sudo -u ${sudoUser} XDG_RUNTIME_DIR=/run/user/$(id -u ${sudoUser}) systemctl --user stop ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
495
|
+
} catch {
|
|
496
|
+
// Service might not be running
|
|
497
|
+
}
|
|
498
|
+
try {
|
|
499
|
+
execSync(`sudo -u ${sudoUser} XDG_RUNTIME_DIR=/run/user/$(id -u ${sudoUser}) systemctl --user disable ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
500
|
+
} catch {
|
|
501
|
+
// Service might not be enabled
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
fs.unlinkSync(effectiveUserUnitPath);
|
|
505
|
+
console.log(`[AxonRouter] Removed ${effectiveUserUnitPath}`);
|
|
506
|
+
} catch {
|
|
507
|
+
// File might not exist
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
execSync(`sudo -u ${sudoUser} XDG_RUNTIME_DIR=/run/user/$(id -u ${sudoUser}) systemctl --user daemon-reload`, { stdio: "inherit" });
|
|
511
|
+
} catch {
|
|
512
|
+
// daemon-reload may fail if session not available, but file is already removed
|
|
513
|
+
}
|
|
514
|
+
console.log(`[AxonRouter] User-level service for ${sudoUser} uninstalled.`);
|
|
515
|
+
} else if (systemLevelExists) {
|
|
516
|
+
// Uninstall system-level service
|
|
517
|
+
try {
|
|
518
|
+
runWithSudo(`systemctl stop ${SERVICE_NAME}`);
|
|
519
|
+
} catch {
|
|
520
|
+
// Service might not be running
|
|
521
|
+
}
|
|
522
|
+
try {
|
|
523
|
+
runWithSudo(`systemctl disable ${SERVICE_NAME}`);
|
|
524
|
+
} catch {
|
|
525
|
+
// Service might not be enabled
|
|
526
|
+
}
|
|
527
|
+
try {
|
|
528
|
+
runWithSudo(`rm -f ${SYSTEMD_UNIT_PATH}`);
|
|
529
|
+
console.log(`[AxonRouter] Removed ${SYSTEMD_UNIT_PATH}`);
|
|
530
|
+
} catch {
|
|
531
|
+
// File might not exist
|
|
532
|
+
}
|
|
533
|
+
runWithSudo("systemctl daemon-reload");
|
|
534
|
+
console.log(`[AxonRouter] System-level service uninstalled.`);
|
|
535
|
+
} else {
|
|
536
|
+
console.log(`[AxonRouter] No service found to uninstall.`);
|
|
287
537
|
}
|
|
288
|
-
runWithSudo("systemctl daemon-reload");
|
|
289
|
-
console.log(`[AxonRouter] Service uninstalled.`);
|
|
290
538
|
} else {
|
|
291
539
|
try {
|
|
292
540
|
runWithSudo(`${INITD_SCRIPT_PATH} stop`);
|
|
@@ -319,6 +567,7 @@ export function uninstallService() {
|
|
|
319
567
|
|
|
320
568
|
/**
|
|
321
569
|
* Check the status of the service.
|
|
570
|
+
* Checks both user-level and system-level unit paths and reports status.
|
|
322
571
|
*/
|
|
323
572
|
export function checkService() {
|
|
324
573
|
const initSystem = detectInitSystem();
|
|
@@ -326,17 +575,33 @@ export function checkService() {
|
|
|
326
575
|
console.log(`[AxonRouter] Init system: ${initSystem}`);
|
|
327
576
|
|
|
328
577
|
if (initSystem === "systemd") {
|
|
329
|
-
const
|
|
330
|
-
|
|
578
|
+
const userLevelExists = fs.existsSync(USER_UNIT_PATH);
|
|
579
|
+
const systemLevelExists = fs.existsSync(SYSTEMD_UNIT_PATH);
|
|
331
580
|
|
|
332
|
-
if (
|
|
581
|
+
if (userLevelExists) {
|
|
582
|
+
console.log(`[AxonRouter] User-level service installed: ${USER_UNIT_PATH}`);
|
|
333
583
|
try {
|
|
334
|
-
const status = execSync(`systemctl is-active ${SERVICE_NAME}`, { encoding: "utf-8" }).trim();
|
|
584
|
+
const status = execSync(`systemctl --user is-active ${SERVICE_NAME}`, { encoding: "utf-8" }).trim();
|
|
335
585
|
console.log(`[AxonRouter] Service status: ${status}`);
|
|
336
|
-
} catch
|
|
586
|
+
} catch {
|
|
337
587
|
console.log(`[AxonRouter] Service status: inactive`);
|
|
338
588
|
}
|
|
589
|
+
try {
|
|
590
|
+
const enabled = execSync(`systemctl --user is-enabled ${SERVICE_NAME}`, { encoding: "utf-8" }).trim();
|
|
591
|
+
console.log(`[AxonRouter] Service enabled: ${enabled}`);
|
|
592
|
+
} catch {
|
|
593
|
+
console.log(`[AxonRouter] Service enabled: disabled`);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
339
596
|
|
|
597
|
+
if (systemLevelExists) {
|
|
598
|
+
console.log(`[AxonRouter] System-level service installed: ${SYSTEMD_UNIT_PATH}`);
|
|
599
|
+
try {
|
|
600
|
+
const status = execSync(`systemctl is-active ${SERVICE_NAME}`, { encoding: "utf-8" }).trim();
|
|
601
|
+
console.log(`[AxonRouter] Service status: ${status}`);
|
|
602
|
+
} catch {
|
|
603
|
+
console.log(`[AxonRouter] Service status: inactive`);
|
|
604
|
+
}
|
|
340
605
|
try {
|
|
341
606
|
const enabled = execSync(`systemctl is-enabled ${SERVICE_NAME}`, { encoding: "utf-8" }).trim();
|
|
342
607
|
console.log(`[AxonRouter] Service enabled: ${enabled}`);
|
|
@@ -344,6 +609,10 @@ export function checkService() {
|
|
|
344
609
|
console.log(`[AxonRouter] Service enabled: disabled`);
|
|
345
610
|
}
|
|
346
611
|
}
|
|
612
|
+
|
|
613
|
+
if (!userLevelExists && !systemLevelExists) {
|
|
614
|
+
console.log(`[AxonRouter] Service installed: false`);
|
|
615
|
+
}
|
|
347
616
|
} else {
|
|
348
617
|
const installed = fs.existsSync(INITD_SCRIPT_PATH);
|
|
349
618
|
console.log(`[AxonRouter] Service installed: ${installed}`);
|
|
@@ -360,12 +629,24 @@ export function checkService() {
|
|
|
360
629
|
|
|
361
630
|
/**
|
|
362
631
|
* Start the service.
|
|
632
|
+
* Checks for user-level service (including via SUDO_USER when root).
|
|
363
633
|
*/
|
|
364
634
|
export function startService() {
|
|
365
635
|
const initSystem = detectInitSystem();
|
|
366
636
|
|
|
367
637
|
if (initSystem === "systemd") {
|
|
368
|
-
|
|
638
|
+
const sudoUser = process.env.SUDO_USER;
|
|
639
|
+
const effectiveUserUnitPath = (isRoot() && sudoUser)
|
|
640
|
+
? getUserUnitPath(sudoUser)
|
|
641
|
+
: USER_UNIT_PATH;
|
|
642
|
+
|
|
643
|
+
if (fs.existsSync(effectiveUserUnitPath) && !isRoot()) {
|
|
644
|
+
execSync(`systemctl --user start ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
645
|
+
} else if (fs.existsSync(effectiveUserUnitPath) && isRoot() && sudoUser) {
|
|
646
|
+
execSync(`sudo -u ${sudoUser} XDG_RUNTIME_DIR=/run/user/$(id -u ${sudoUser}) systemctl --user start ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
647
|
+
} else {
|
|
648
|
+
runWithSudo(`systemctl start ${SERVICE_NAME}`);
|
|
649
|
+
}
|
|
369
650
|
} else {
|
|
370
651
|
runWithSudo(`${INITD_SCRIPT_PATH} start`);
|
|
371
652
|
}
|
|
@@ -375,12 +656,24 @@ export function startService() {
|
|
|
375
656
|
|
|
376
657
|
/**
|
|
377
658
|
* Stop the service.
|
|
659
|
+
* Checks for user-level service (including via SUDO_USER when root).
|
|
378
660
|
*/
|
|
379
661
|
export function stopService() {
|
|
380
662
|
const initSystem = detectInitSystem();
|
|
381
663
|
|
|
382
664
|
if (initSystem === "systemd") {
|
|
383
|
-
|
|
665
|
+
const sudoUser = process.env.SUDO_USER;
|
|
666
|
+
const effectiveUserUnitPath = (isRoot() && sudoUser)
|
|
667
|
+
? getUserUnitPath(sudoUser)
|
|
668
|
+
: USER_UNIT_PATH;
|
|
669
|
+
|
|
670
|
+
if (fs.existsSync(effectiveUserUnitPath) && !isRoot()) {
|
|
671
|
+
execSync(`systemctl --user stop ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
672
|
+
} else if (fs.existsSync(effectiveUserUnitPath) && isRoot() && sudoUser) {
|
|
673
|
+
execSync(`sudo -u ${sudoUser} XDG_RUNTIME_DIR=/run/user/$(id -u ${sudoUser}) systemctl --user stop ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
674
|
+
} else {
|
|
675
|
+
runWithSudo(`systemctl stop ${SERVICE_NAME}`);
|
|
676
|
+
}
|
|
384
677
|
} else {
|
|
385
678
|
runWithSudo(`${INITD_SCRIPT_PATH} stop`);
|
|
386
679
|
}
|
|
@@ -390,12 +683,24 @@ export function stopService() {
|
|
|
390
683
|
|
|
391
684
|
/**
|
|
392
685
|
* Restart the service.
|
|
686
|
+
* Checks for user-level service (including via SUDO_USER when root).
|
|
393
687
|
*/
|
|
394
688
|
export function restartService() {
|
|
395
689
|
const initSystem = detectInitSystem();
|
|
396
690
|
|
|
397
691
|
if (initSystem === "systemd") {
|
|
398
|
-
|
|
692
|
+
const sudoUser = process.env.SUDO_USER;
|
|
693
|
+
const effectiveUserUnitPath = (isRoot() && sudoUser)
|
|
694
|
+
? getUserUnitPath(sudoUser)
|
|
695
|
+
: USER_UNIT_PATH;
|
|
696
|
+
|
|
697
|
+
if (fs.existsSync(effectiveUserUnitPath) && !isRoot()) {
|
|
698
|
+
execSync(`systemctl --user restart ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
699
|
+
} else if (fs.existsSync(effectiveUserUnitPath) && isRoot() && sudoUser) {
|
|
700
|
+
execSync(`sudo -u ${sudoUser} XDG_RUNTIME_DIR=/run/user/$(id -u ${sudoUser}) systemctl --user restart ${SERVICE_NAME}`, { stdio: "inherit" });
|
|
701
|
+
} else {
|
|
702
|
+
runWithSudo(`systemctl restart ${SERVICE_NAME}`);
|
|
703
|
+
}
|
|
399
704
|
} else {
|
|
400
705
|
runWithSudo(`${INITD_SCRIPT_PATH} restart`);
|
|
401
706
|
}
|
|
@@ -407,8 +712,14 @@ export function restartService() {
|
|
|
407
712
|
* Show help message with available commands.
|
|
408
713
|
*/
|
|
409
714
|
export function showHelp() {
|
|
715
|
+
let version = "unknown";
|
|
716
|
+
try {
|
|
717
|
+
const pkgUrl = new URL("../package.json", import.meta.url);
|
|
718
|
+
version = JSON.parse(fs.readFileSync(pkgUrl, "utf8")).version;
|
|
719
|
+
} catch {}
|
|
720
|
+
|
|
410
721
|
console.log(`
|
|
411
|
-
\x1b[1mAxonRouter - AI Router
|
|
722
|
+
\x1b[1mAxonRouter v${version} - AI Router\x1b[0m
|
|
412
723
|
|
|
413
724
|
\x1b[33mUsage:\x1b[0m
|
|
414
725
|
axonrouter <command> [options]
|
|
@@ -436,7 +747,8 @@ export function showHelp() {
|
|
|
436
747
|
axonrouter --port 3000 Start on custom port
|
|
437
748
|
|
|
438
749
|
\x1b[33mNotes:\x1b[0m
|
|
439
|
-
|
|
750
|
+
When not running as root, service installs as a user-level systemd service.
|
|
751
|
+
When running as root, service installs as a system-level service.
|
|
440
752
|
The service auto-restarts on crash (systemd: always, init.d: up to 10 times).
|
|
441
753
|
`);
|
|
442
754
|
}
|