feat: add multi-agent beta remote office support (#62)

* Remote openclaw connection enabled and agent added

* 2 worlds connected

* Performance improvement

* Performance improvements

* Added documentation

* feat(office): add multi-agent beta remote office support

Add a second-office beta that can mirror remote Claw3D presence or derive remote gateway presence so teams can visualize and message agents across instances. Harden the new remote flows, document setup, and keep the branch green with full validation.

Made-with: Cursor

---------

Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
Co-authored-by: iamlukethedev <lucas.guilherme@smartwayslfl.com>
This commit is contained in:
Luke The Dev
2026-03-25 11:14:20 -05:00
committed by GitHub
parent 1185f7a9f0
commit a202cdc80f
31 changed files with 4326 additions and 467 deletions
+4 -5
View File
@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import { CANVAS_H, CANVAS_W } from "@/features/retro-office/core/constants";
import { astar, buildNavGrid } from "@/features/retro-office/core/navigation";
import { ITEM_METADATA } from "@/features/retro-office/core/geometry";
import type { FurnitureItem } from "@/features/retro-office/core/types";
@@ -24,8 +25,6 @@ const isBlocked = (
wh = 30,
): boolean => {
const GRID_CELL = 25;
const CANVAS_W = 1800;
const CANVAS_H = 720;
const GRID_COLS = Math.ceil(CANVAS_W / GRID_CELL);
const GRID_ROWS = Math.ceil(CANVAS_H / GRID_CELL);
@@ -152,14 +151,14 @@ describe("buildNavGrid near-boundary placement (issue #4)", () => {
it("blocking item near the grid edge does not cause out-of-bounds errors", () => {
// Place a large item near the right/bottom edges of the canvas.
// buildNavGrid clamps cells to valid indices — this must not throw.
const nearEdge = makeItem("cabinet", 1760, 680); // close to CANVAS_W=1800, CANVAS_H=720
const nearEdge = makeItem("cabinet", CANVAS_W - 40, CANVAS_H - 40);
expect(() => buildNavGrid([nearEdge])).not.toThrow();
const grid = buildNavGrid([nearEdge]);
// The grid array length must still be correct.
const GRID_CELL = 25;
const GRID_COLS = Math.ceil(1800 / GRID_CELL);
const GRID_ROWS = Math.ceil(720 / GRID_CELL);
const GRID_COLS = Math.ceil(CANVAS_W / GRID_CELL);
const GRID_ROWS = Math.ceil(CANVAS_H / GRID_CELL);
expect(grid.length).toBe(GRID_COLS * GRID_ROWS);
});
+15 -9
View File
@@ -156,12 +156,16 @@ describe("studio settings normalization", () => {
},
});
expect(normalized.office["ws://localhost:18789"]).toEqual({
title: "Team Orbit",
});
expect(normalized.office.bad).toEqual({
title: "Luke Headquarters",
});
expect(normalized.office["ws://localhost:18789"]).toEqual(
expect.objectContaining({
title: "Team Orbit",
}),
);
expect(normalized.office.bad).toEqual(
expect.objectContaining({
title: "Luke Headquarters",
}),
);
});
it("merges office title patches", () => {
@@ -181,8 +185,10 @@ describe("studio settings normalization", () => {
},
});
expect(merged.office["ws://localhost:18789"]).toEqual({
title: "Orbit Control",
});
expect(merged.office["ws://localhost:18789"]).toEqual(
expect.objectContaining({
title: "Orbit Control",
}),
);
});
});
+10 -6
View File
@@ -107,9 +107,11 @@ describe("studio settings route", () => {
url: "ws://example.test:1234",
tokenConfigured: true,
});
expect(body.settings?.office?.["ws://example.test:1234"]).toEqual({
title: "Orbit Control",
});
expect(body.settings?.office?.["ws://example.test:1234"]).toEqual(
expect.objectContaining({
title: "Orbit Control",
}),
);
const settingsPath = path.join(tempDir, "claw3d", "settings.json");
expect(fs.existsSync(settingsPath)).toBe(true);
@@ -119,8 +121,10 @@ describe("studio settings route", () => {
office?: Record<string, { title?: string }>;
};
expect(parsed.gateway).toEqual({ url: "ws://example.test:1234", token: "t" });
expect(parsed.office?.["ws://example.test:1234"]).toEqual({
title: "Orbit Control",
});
expect(parsed.office?.["ws://example.test:1234"]).toEqual(
expect.objectContaining({
title: "Orbit Control",
}),
);
});
});