clay-server 4.0.0-beta.22 → 4.0.0-beta.23

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.
@@ -1,4 +1,4 @@
1
- // One-shot boot routing after durable Home preferences become available.
1
+ // One-shot routing for a server-selected project or the no-project Home fallback.
2
2
  import { store } from './store.js';
3
3
  import { rememberHomePrimarySurface } from './home-surface.js';
4
4
 
@@ -10,9 +10,13 @@ function explicitProjectPath(pathname) {
10
10
  }
11
11
 
12
12
  export function resolveHomeBootDestination(options) {
13
- if (!options || options.surfaceLoaded !== true) return "wait";
13
+ if (!options) return "wait";
14
14
  if (options.paneMode || explicitProjectPath(options.pathname)) return "project";
15
- if (options.surface === "project" && options.currentSlug) return "project";
15
+ // The server-selected project embedded in the root shell is authoritative.
16
+ // Home is entered only through an explicit in-app action; reloading `/`
17
+ // returns to the project workspace even if Home was the last open surface.
18
+ if (options.currentSlug) return "project";
19
+ if (options.surfaceLoaded !== true) return "wait";
16
20
  if (options.dockLoaded !== true) return "wait";
17
21
  return "home";
18
22
  }
package/lib/server.js CHANGED
@@ -124,6 +124,14 @@ function stripPrefix(urlPath, slug) {
124
124
  return rest || "/";
125
125
  }
126
126
 
127
+ function injectRootProjectSlug(html, slug) {
128
+ var bodyPattern = /<body\b([^>]*)>/i;
129
+ if (!bodyPattern.test(html)) throw new Error("App shell body is missing");
130
+ return html.replace(bodyPattern, function (_match, attributes) {
131
+ return '<body' + attributes + ' data-home-project-slug="' + slug + '">';
132
+ });
133
+ }
134
+
127
135
  /**
128
136
  * Create a multi-project server.
129
137
  * opts: { tlsOptions, caPath, pinHash, port, debug, dangerouslySkipPermissions }
@@ -741,7 +749,8 @@ function createServer(opts) {
741
749
  // --- Skills routes (delegated to server-skills) ---
742
750
  if (skills.handleRequest(req, res, fullUrl)) return;
743
751
 
744
- // Root path — render home while keeping the last accessible project connected.
752
+ // Root path — render the default project workspace while keeping Home
753
+ // available as an explicit client-side surface.
745
754
  if (fullUrl === "/" && req.method === "GET") {
746
755
  if (!isRequestAuthed(req)) {
747
756
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -751,11 +760,16 @@ function createServer(opts) {
751
760
  if (projects.size > 0) {
752
761
  var targetSlug = null;
753
762
  var reqUser = users.isMultiUser() ? getMultiUserFromReq(req) : null;
763
+ function isOrdinaryProject(slug) {
764
+ var candidate = slug ? projects.get(slug) : null;
765
+ var status = candidate && candidate.getStatus ? candidate.getStatus() : null;
766
+ return !!candidate && (!status || status.isMate !== true);
767
+ }
754
768
  var homePreference = typeof users.getHomeSurfacePreference === "function"
755
769
  ? users.getHomeSurfacePreference(reqUser ? reqUser.id : "default")
756
770
  : null;
757
771
  var preferredContextSlug = homePreference && homePreference.projectSlug;
758
- if (preferredContextSlug && projects.has(preferredContextSlug)) {
772
+ if (isOrdinaryProject(preferredContextSlug)) {
759
773
  if (reqUser && onGetProjectAccess) {
760
774
  var preferredAccess = onGetProjectAccess(preferredContextSlug);
761
775
  if (preferredAccess && !preferredAccess.error && users.canAccessProject(reqUser.id, preferredAccess)) {
@@ -767,7 +781,7 @@ function createServer(opts) {
767
781
  }
768
782
  // Check for last-visited project cookie
769
783
  var lastProject = parseCookies(req)["clay_last_project"];
770
- if (!targetSlug && lastProject && projects.has(lastProject)) {
784
+ if (!targetSlug && isOrdinaryProject(lastProject)) {
771
785
  if (reqUser && onGetProjectAccess) {
772
786
  var lpAccess = onGetProjectAccess(lastProject);
773
787
  if (lpAccess && !lpAccess.error && users.canAccessProject(reqUser.id, lpAccess)) {
@@ -781,6 +795,7 @@ function createServer(opts) {
781
795
  if (!targetSlug) {
782
796
  projects.forEach(function (ctx, s) {
783
797
  if (targetSlug) return;
798
+ if (!isOrdinaryProject(s)) return;
784
799
  if (reqUser && onGetProjectAccess) {
785
800
  var access = onGetProjectAccess(s);
786
801
  if (access && !access.error && users.canAccessProject(reqUser.id, access)) {
@@ -794,7 +809,7 @@ function createServer(opts) {
794
809
  if (targetSlug) {
795
810
  try {
796
811
  var homeHtml = fs.readFileSync(path.join(publicDir, "index.html"), "utf8");
797
- homeHtml = homeHtml.replace("<body>", '<body data-home-project-slug="' + targetSlug + '">');
812
+ homeHtml = injectRootProjectSlug(homeHtml, targetSlug);
798
813
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-cache" });
799
814
  res.end(homeHtml);
800
815
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "4.0.0-beta.22",
3
+ "version": "4.0.0-beta.23",
4
4
  "description": "Self-hosted team workspace for Claude Code and Codex. Multi-user, browser-based, with persistent AI mates.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",