diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 724034d..fd00236 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,11 +53,11 @@ jobs: - name: Cache OpenRA engine uses: actions/cache@v4 with: - path: command-and-clanker/engine - key: openra-engine-${{ runner.os }}-${{ hashFiles('command-and-clanker/mod.config') }} + path: command-and-combobulate/engine + key: openra-engine-${{ runner.os }}-${{ hashFiles('command-and-combobulate/mod.config') }} restore-keys: | openra-engine-${{ runner.os }}- - name: Build mod - working-directory: command-and-clanker + working-directory: command-and-combobulate run: make diff --git a/.gitignore b/.gitignore index ab3f2d3..0e7850a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ dist/ .vite/ *.log .DS_Store -.clanker-cache.json +.combobulate-cache.json diff --git a/AGENTS.md b/AGENTS.md index 31b910f..6ca39ed 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ conventions an agent needs to make changes safely. ## What this repo is -Command & Clanker visualises an AI agent's tool calls as an +Command & Combobulate visualises an AI agent's tool calls as an [OpenRA](https://www.openra.net) real-time strategy game. The agent's terminal is a building, files are smaller buildings inside folder compounds, and every read/write/run shows up as a unit moving on the map. @@ -17,13 +17,13 @@ It ships as two cooperating pieces that talk over WebSocket and HTTP on - **`server/`** — a Node backend. Hosts real PTYs via `node-pty`, ingests tool events posted by the agent adapters, builds a world model, and streams it to connected game clients. -- **`command-and-clanker/`** — an OpenRA Mod SDK mod. A C# client connects to +- **`command-and-combobulate/`** — an OpenRA Mod SDK mod. A C# client connects to the backend, receives world updates, and renders them through the OpenRA engine. The agent adapters in `integrations/` are the third leg: shims for Claude Code and Codex that POST tool calls to the backend, but only when launched from -inside an in-game terminal (detected via the `CLANKER_SESSION` env var). +inside an in-game terminal (detected via the `COMBOBULATE_SESSION` env var). ## Layout @@ -45,10 +45,10 @@ inside an in-game terminal (detected via the `CLANKER_SESSION` env var). Tests sit next to sources as `*.test.ts`. - `shared/` — types shared between the backend and the adapters (`proc-types.ts`, `types.ts`). -- `command-and-clanker/` — the OpenRA mod. Contains an OpenRA SDK scaffold +- `command-and-combobulate/` — the OpenRA mod. Contains an OpenRA SDK scaffold plus: - - `mods/clanker/` — yaml rules, art, maps, and other mod data. - - `OpenRA.Mods.Clanker/` — C# traits and widgets specific to this mod. + - `mods/combobulate/` — yaml rules, art, maps, and other mod data. + - `OpenRA.Mods.Combobulate/` — C# traits and widgets specific to this mod. - `engine/` — fetched OpenRA engine (not checked in; populated by `fetch-engine.sh` / `make`). - `integrations/` — per-agent adapters wired up by `bun run setup`. @@ -70,7 +70,7 @@ The split between Node and Bun is deliberate and load-bearing: - TypeScript is executed via Node's `--experimental-strip-types`; there is no separate build step for the backend. `bun run typecheck` runs `tsc --noEmit`. - The OpenRA mod builds with .NET 8 (or Mono) via `make` inside - `command-and-clanker/`. The first build fetches and compiles the pinned + `command-and-combobulate/`. The first build fetches and compiles the pinned engine and takes several minutes. - `mise.toml` pins Bun and Node versions. @@ -86,7 +86,7 @@ Run from the repo root unless noted: - `bun test` — run all `*.test.ts` files. - `bun run game` — build the mod and launch the game (also starts a backend). -Mod-only flow (from `command-and-clanker/`): +Mod-only flow (from `command-and-combobulate/`): - `make` — fetch the engine on first run, then build the mod. - `./launch-game.sh` / `./launch-dedicated.sh` — launch the game / a dedicated @@ -102,12 +102,12 @@ Mod-only flow (from `command-and-clanker/`): is the canonical example: events in, world state out, no I/O. - Co-locate tests with the code they cover (`foo.ts` + `foo.test.ts`). - The OpenRA mod follows OpenRA's own conventions for yaml rules and C# - traits. When in doubt, mirror an existing trait in `OpenRA.Mods.Clanker/` - or an existing rule in `mods/clanker/`. -- Mod assets (sprites, palettes, maps) live under `mods/clanker/`. Generated - files under `command-and-clanker/engine/` and `bin/` are not checked in. -- Adapters in `integrations/` must stay silent outside a Command & Clanker - session — gate all reporting on `CLANKER_SESSION`. + traits. When in doubt, mirror an existing trait in `OpenRA.Mods.Combobulate/` + or an existing rule in `mods/combobulate/`. +- Mod assets (sprites, palettes, maps) live under `mods/combobulate/`. Generated + files under `command-and-combobulate/engine/` and `bin/` are not checked in. +- Adapters in `integrations/` must stay silent outside a Command & Combobulate + session — gate all reporting on `COMBOBULATE_SESSION`. ## Engineering standards @@ -125,8 +125,8 @@ Mod-only flow (from `command-and-clanker/`): ## Things to avoid -- Do not commit anything under `command-and-clanker/engine/`, - `command-and-clanker/bin/`, or `.clanker-cache.json` — these are +- Do not commit anything under `command-and-combobulate/engine/`, + `command-and-combobulate/bin/`, or `.combobulate-cache.json` — these are build/runtime artefacts. - Do not switch the backend off Node, or the test runner off Bun. - Do not add comments that restate what the code does; follow the diff --git a/README.md b/README.md index ee4e6e3..ff8750f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Command & Clanker -clanker-loadscreen +# Command & Combobulate +Command & Combobulate @@ -14,7 +14,7 @@ It is two pieces: - **`server/`** — a small Node backend. Agent adapters POST their tool calls to it, and it hosts the real terminals (`node-pty`). It streams a live world and terminal I/O over WebSocket. -- **`command-and-clanker/`** — an [OpenRA Mod SDK](https://github.com/OpenRA/OpenRAModSDK) +- **`command-and-combobulate/`** — an [OpenRA Mod SDK](https://github.com/OpenRA/OpenRAModSDK) mod that connects to the backend and renders that world inside the OpenRA engine. ## Prerequisites @@ -37,7 +37,7 @@ In a second shell, build and launch the mod. The first `make` fetches the pinned OpenRA engine and builds it (a few minutes): ```sh -cd command-and-clanker +cd command-and-combobulate make # fetch engine + build the mod ./launch-game.sh # launch ``` @@ -54,7 +54,7 @@ claude # also: codex The agent appears as a unit and starts working the map. Scout outward to reveal what other agents are doing. The adapters only report from inside a Command & -Clanker terminal (where `CLANKER_SESSION` is injected), so they stay quiet +Combobulate terminal (where `COMBOBULATE_SESSION` is injected), so they stay quiet everywhere else. ## What you see @@ -71,8 +71,8 @@ everywhere else. ## Layout - `server/` — the backend (event ingest + PTY hosting). -- `command-and-clanker/` — the OpenRA mod: SDK scaffold, `mods/clanker/` (yaml, - art, maps) and `OpenRA.Mods.Clanker/` (C# traits and widgets). +- `command-and-combobulate/` — the OpenRA mod: SDK scaffold, `mods/combobulate/` (yaml, + art, maps) and `OpenRA.Mods.Combobulate/` (C# traits and widgets). - `integrations/` — the Claude and Codex adapters installed by `bun run setup`. - `docs/` — design notes. diff --git a/assets/loadscreen.png b/assets/loadscreen.png new file mode 100644 index 0000000..ab8606f Binary files /dev/null and b/assets/loadscreen.png differ diff --git a/command-and-clanker/mods/clanker/fluent/clanker.ftl b/command-and-clanker/mods/clanker/fluent/clanker.ftl deleted file mode 100644 index 11110e3..0000000 --- a/command-and-clanker/mods/clanker/fluent/clanker.ftl +++ /dev/null @@ -1,8 +0,0 @@ -clanker-mod-title = Command & Clanker -clanker-mod-windowtitle = Command & Clanker -loadscreen-loading = Comboluating..., Summoning subagents..., Compacting context..., Warming the prompt cache..., Reticulating splines..., Negotiating with the rate limiter..., Spinning up PTYs..., Aligning the clankers..., Tokenizing the vibes..., Deploying robots... -button-clanker-launch = Start Clanking -button-clanker-quit = Quit -actor-clanker-terminal = - .name = Terminal - .description = Spawns a Command & Clanker agent terminal. diff --git a/command-and-clanker/mods/clanker/rules/world.yaml b/command-and-clanker/mods/clanker/rules/world.yaml deleted file mode 100644 index 8bcea3c..0000000 --- a/command-and-clanker/mods/clanker/rules/world.yaml +++ /dev/null @@ -1,7 +0,0 @@ -World: - ClankerBridge: - ClankerSidebarLoader: - LoadWidgetAtGameStart: - ShellmapRoot: CLANKER_MAINMENU - MapOptions: - TechLevel: unrestricted diff --git a/command-and-clanker/mods/clanker/uibits/clanker-loadscreen-2x.png b/command-and-clanker/mods/clanker/uibits/clanker-loadscreen-2x.png deleted file mode 100644 index f6edc57..0000000 Binary files a/command-and-clanker/mods/clanker/uibits/clanker-loadscreen-2x.png and /dev/null differ diff --git a/command-and-clanker/mods/clanker/uibits/clanker-loadscreen-3x.png b/command-and-clanker/mods/clanker/uibits/clanker-loadscreen-3x.png deleted file mode 100644 index a93e362..0000000 Binary files a/command-and-clanker/mods/clanker/uibits/clanker-loadscreen-3x.png and /dev/null differ diff --git a/command-and-clanker/mods/clanker/uibits/clanker-loadscreen.png b/command-and-clanker/mods/clanker/uibits/clanker-loadscreen.png deleted file mode 100644 index 0013684..0000000 Binary files a/command-and-clanker/mods/clanker/uibits/clanker-loadscreen.png and /dev/null differ diff --git a/command-and-clanker/package.json b/command-and-clanker/package.json deleted file mode 100644 index c012046..0000000 --- a/command-and-clanker/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "command-and-clanker-mod", - "version": "0.1.0", - "private": true, - "description": "Command & Clanker OpenRA mod (built on the OpenRA Mod SDK).", - "scripts": { - "build": "make", - "launch": "./launch-game.sh", - "game": "make && ./launch-game.sh", - "utility": "./utility.sh clanker" - } -} diff --git a/command-and-clanker/.editorconfig b/command-and-combobulate/.editorconfig similarity index 100% rename from command-and-clanker/.editorconfig rename to command-and-combobulate/.editorconfig diff --git a/command-and-clanker/.gitattributes b/command-and-combobulate/.gitattributes similarity index 100% rename from command-and-clanker/.gitattributes rename to command-and-combobulate/.gitattributes diff --git a/command-and-clanker/.gitignore b/command-and-combobulate/.gitignore similarity index 100% rename from command-and-clanker/.gitignore rename to command-and-combobulate/.gitignore diff --git a/command-and-clanker/.vscode/extensions.json b/command-and-combobulate/.vscode/extensions.json similarity index 100% rename from command-and-clanker/.vscode/extensions.json rename to command-and-combobulate/.vscode/extensions.json diff --git a/command-and-clanker/.vscode/launch.json b/command-and-combobulate/.vscode/launch.json similarity index 100% rename from command-and-clanker/.vscode/launch.json rename to command-and-combobulate/.vscode/launch.json diff --git a/command-and-clanker/.vscode/tasks.json b/command-and-combobulate/.vscode/tasks.json similarity index 100% rename from command-and-clanker/.vscode/tasks.json rename to command-and-combobulate/.vscode/tasks.json diff --git a/command-and-clanker/COPYING b/command-and-combobulate/COPYING similarity index 100% rename from command-and-clanker/COPYING rename to command-and-combobulate/COPYING diff --git a/command-and-clanker/CommandAndClanker.sln b/command-and-combobulate/CommandAndCombobulate.sln similarity index 95% rename from command-and-clanker/CommandAndClanker.sln rename to command-and-combobulate/CommandAndCombobulate.sln index a1df25f..00216a1 100644 --- a/command-and-clanker/CommandAndClanker.sln +++ b/command-and-combobulate/CommandAndCombobulate.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Mods.Clanker", "OpenRA.Mods.Clanker\OpenRA.Mods.Clanker.csproj", "{4E5B38F7-4E99-4C92-BB39-9100CC7F3829}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Mods.Combobulate", "OpenRA.Mods.Combobulate\OpenRA.Mods.Combobulate.csproj", "{4E5B38F7-4E99-4C92-BB39-9100CC7F3829}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Game", "engine\OpenRA.Game\OpenRA.Game.csproj", "{0DFB103F-2962-400F-8C6D-E2C28CCBA633}" EndProject diff --git a/command-and-clanker/Makefile b/command-and-combobulate/Makefile similarity index 100% rename from command-and-clanker/Makefile rename to command-and-combobulate/Makefile diff --git a/command-and-clanker/OpenRA.Mods.Clanker/ClankerBackend.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/CombobulateBackend.cs similarity index 92% rename from command-and-clanker/OpenRA.Mods.Clanker/ClankerBackend.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/CombobulateBackend.cs index cf20192..d32c347 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/ClankerBackend.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/CombobulateBackend.cs @@ -5,13 +5,13 @@ using System.Threading.Tasks; using OpenRA.Support; -namespace OpenRA.Mods.Clanker +namespace OpenRA.Mods.Combobulate { - // Fire-and-forget JSON POSTs to the Command & Clanker backend. Called from the + // Fire-and-forget JSON POSTs to the Command & Combobulate backend. Called from the // game thread; the request runs on a background task so it never stalls a tick. // Anything that changes the world comes back over the bridge's /live stream, // so callers do not await a response. - public static class ClankerBackend + public static class CombobulateBackend { public static string BaseUrl = "http://127.0.0.1:3001"; diff --git a/command-and-clanker/OpenRA.Mods.Clanker/ClankerLoadScreen.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/CombobulateLoadScreen.cs similarity index 95% rename from command-and-clanker/OpenRA.Mods.Clanker/ClankerLoadScreen.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/CombobulateLoadScreen.cs index 22f2f41..fa7e9ed 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/ClankerLoadScreen.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/CombobulateLoadScreen.cs @@ -4,14 +4,14 @@ using OpenRA.Mods.Common.LoadScreens; using OpenRA.Primitives; -namespace OpenRA.Mods.Clanker +namespace OpenRA.Mods.Combobulate { // Draws a single image centered on screen plus the loadscreen-loading phrases. // Unlike LogoStripeLoadScreen (which tiles a "stripe" region across the full // width and so mangles a plain banner), this shows the image exactly once. // Image size defaults to 512x256 and can be overridden with Width/Height in // the LoadScreen block. - public sealed class ClankerLoadScreen : SheetLoadScreen + public sealed class CombobulateLoadScreen : SheetLoadScreen { [FluentReference] const string Loading = "loadscreen-loading"; diff --git a/command-and-clanker/OpenRA.Mods.Clanker/MapCoords.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/MapCoords.cs similarity index 91% rename from command-and-clanker/OpenRA.Mods.Clanker/MapCoords.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/MapCoords.cs index 5dd3e32..2eb813b 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/MapCoords.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/MapCoords.cs @@ -1,6 +1,6 @@ -using OpenRA.Mods.Clanker.Protocol; +using OpenRA.Mods.Combobulate.Protocol; -namespace OpenRA.Mods.Clanker +namespace OpenRA.Mods.Combobulate { // Translates the backend's unbounded tile grid (Region.origin / fileArea, // laid out by the spiral slot allocator in server/world-builder.ts) onto a diff --git a/command-and-clanker/OpenRA.Mods.Clanker/OpenRA.Mods.Clanker.csproj b/command-and-combobulate/OpenRA.Mods.Combobulate/OpenRA.Mods.Combobulate.csproj similarity index 100% rename from command-and-clanker/OpenRA.Mods.Clanker/OpenRA.Mods.Clanker.csproj rename to command-and-combobulate/OpenRA.Mods.Combobulate/OpenRA.Mods.Combobulate.csproj diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Protocol/LiveMessage.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Protocol/LiveMessage.cs similarity index 97% rename from command-and-clanker/OpenRA.Mods.Clanker/Protocol/LiveMessage.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Protocol/LiveMessage.cs index 88d57ca..656dad5 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Protocol/LiveMessage.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Protocol/LiveMessage.cs @@ -2,9 +2,9 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace OpenRA.Mods.Clanker.Protocol +namespace OpenRA.Mods.Combobulate.Protocol { - // Mirrors the wire format the Command & Clanker backend broadcasts over + // Mirrors the wire format the Command & Combobulate backend broadcasts over // WS /live (see the LiveMessage union in shared/proc-types.ts). One inbound // frame is one of three kinds: a full world snapshot ("world-delta"), the // current agents ("agents"), or the files each folder has touched ("files"). diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerBridge.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateBridge.cs similarity index 93% rename from command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerBridge.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateBridge.cs index 5e71947..8f7e690 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerBridge.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateBridge.cs @@ -8,7 +8,7 @@ using System.Threading; using System.Threading.Tasks; using OpenRA.Graphics; -using OpenRA.Mods.Clanker.Protocol; +using OpenRA.Mods.Combobulate.Protocol; using OpenRA.Mods.Common; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Effects; @@ -17,13 +17,13 @@ using OpenRA.Primitives; using OpenRA.Traits; -namespace OpenRA.Mods.Clanker.Traits +namespace OpenRA.Mods.Combobulate.Traits { [TraitLocation(SystemActors.World)] - [Desc("Connects to the Command & Clanker backend over WebSocket and renders", + [Desc("Connects to the Command & Combobulate backend over WebSocket and renders", "its live world (terminal islands, folder regions, and the files agents", "touch) as actors and resources on the map.")] - public class ClankerBridgeInfo : TraitInfo + public class CombobulateBridgeInfo : TraitInfo { [Desc("Backend WebSocket endpoint for the live world stream.")] public readonly string LiveUrl = "ws://127.0.0.1:3001/live"; @@ -33,7 +33,7 @@ public class ClankerBridgeInfo : TraitInfo [ActorReference] [Desc("Actor spawned for each terminal island.")] - public readonly string TerminalActor = "clanker.terminal"; + public readonly string TerminalActor = "combobulate.terminal"; [Desc("Wall actors placed around folder perimeters, chosen by nesting depth", "(level 0 = outermost). The last entry covers any deeper level.")] @@ -41,28 +41,28 @@ public class ClankerBridgeInfo : TraitInfo [ActorReference] [Desc("Wall actor for a folder's top-left corner; it carries the folder name label.")] - public readonly string FolderLabelWall = "clanker.folderwall"; + public readonly string FolderLabelWall = "combobulate.folderwall"; [ActorReference] [Desc("Civilian building actors placed inside a folder, one per file an agent", "touches; the variant is chosen by file extension so similar files match.")] public readonly string[] FileActors = { - "clanker.file1", "clanker.file2", "clanker.file3", - "clanker.file4", "clanker.file5", "clanker.file6", "clanker.file7", + "combobulate.file1", "combobulate.file2", "combobulate.file3", + "combobulate.file4", "combobulate.file5", "combobulate.file6", "combobulate.file7", }; [ActorReference] [Desc("Unit spawned for each agent (Claude / default), homed on its terminal island.")] - public readonly string AgentActor = "clanker.agent"; + public readonly string AgentActor = "combobulate.agent"; [ActorReference] [Desc("Unit for codex agents.")] - public readonly string CodexAgentActor = "clanker.agent.codex"; + public readonly string CodexAgentActor = "combobulate.agent.codex"; [ActorReference] [Desc("Unit spawned for each subagent.")] - public readonly string SubagentActor = "clanker.subagent"; + public readonly string SubagentActor = "combobulate.subagent"; [ActorReference] [Desc("Transient machines spawned at an action site, one per verb, that", @@ -87,25 +87,25 @@ public class ClankerBridgeInfo : TraitInfo "until they are scouted.")] public readonly string OwnerPlayer = "Neutral"; - public override object Create(ActorInitializer init) { return new ClankerBridge(this); } + public override object Create(ActorInitializer init) { return new CombobulateBridge(this); } } // The background thread only ever touches the ConcurrentQueue; every World, // Actor, Map, and resource access happens on the game thread inside ITick and // the AddFrameEndTask it schedules. That boundary is what keeps the bridge safe. - public class ClankerBridge : IWorldLoaded, ITick, INotifyActorDisposing, IRenderAnnotations + public class CombobulateBridge : IWorldLoaded, ITick, INotifyActorDisposing, IRenderAnnotations { - readonly ClankerBridgeInfo info; + readonly CombobulateBridgeInfo info; readonly ConcurrentQueue inbox = new(); readonly Dictionary islands = new(); - readonly Dictionary islandRefs = new(); + readonly Dictionary islandRefs = new(); readonly Dictionary> folderWalls = new(); readonly Dictionary folderRegions = new(); readonly Dictionary> placedFiles = new(); readonly Dictionary agents = new(); readonly Dictionary agentHome = new(); readonly Dictionary agentTarget = new(); - readonly Dictionary agentLabels = new(); + readonly Dictionary agentLabels = new(); // Current action key (verb|path) per agent: spawn the verb machine once // when this changes. The agent's start state (ok null) is collapsed into // the completion server-side before broadcast, so keying on ok would @@ -119,11 +119,11 @@ public class ClankerBridge : IWorldLoaded, ITick, INotifyActorDisposing, IRender CancellationTokenSource termCts; string streamedId; - volatile ClankerTermGrid termGrid; + volatile CombobulateTermGrid termGrid; readonly ConcurrentQueue termSend = new(); // The selected terminal's resolved screen, repainted by the terminal widget. - public ClankerTermGrid TerminalGrid => termGrid; + public CombobulateTermGrid TerminalGrid => termGrid; // The id of the terminal currently mirrored, or null when none is selected. public string StreamedTerminal => streamedId; @@ -149,7 +149,7 @@ public class ClankerBridge : IWorldLoaded, ITick, INotifyActorDisposing, IRender MapCoords coords; CancellationTokenSource cts; - public ClankerBridge(ClankerBridgeInfo info) + public CombobulateBridge(CombobulateBridgeInfo info) { this.info = info; } @@ -158,7 +158,7 @@ void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr) { world = w; owner = FindOwner(w); - ClankerBackend.BaseUrl = info.HttpUrl; + CombobulateBackend.BaseUrl = info.HttpUrl; var bounds = w.Map.Bounds; // Anchor the agent world just south-east of the commander's base (top-left) @@ -198,7 +198,7 @@ public void RegisterPlayerTerminal(string id, Actor actor) return; islands[id] = actor; - islandRefs[id] = actor.TraitOrDefault(); + islandRefs[id] = actor.TraitOrDefault(); } async Task RunSocketLoop(CancellationToken ct) @@ -291,10 +291,10 @@ void ApplyRegions(World w, List regions) [ new LocationInit(cell), new OwnerInit(owner), - new ClankerTerminalRefInit(region.Path), + new CombobulateTerminalRefInit(region.Path), ]); islands[region.Path] = island; - islandRefs[region.Path] = island.TraitOrDefault(); + islandRefs[region.Path] = island.TraitOrDefault(); } } } @@ -375,7 +375,7 @@ List BuildFolderWalls(World w, Region region) if (isLabelCorner) { - var label = actor.TraitOrDefault(); + var label = actor.TraitOrDefault(); if (label != null) label.Label = name; } @@ -432,7 +432,7 @@ void UpdateTerminalLabel(string terminal, double? fraction, string message) if (!islands.TryGetValue(terminal, out var island) || !island.IsInWorld) return; - var label = island.TraitOrDefault(); + var label = island.TraitOrDefault(); if (label == null) return; @@ -643,7 +643,7 @@ void ApplyFiles(World w, List files) new LocationInit(cells[chosen]), new OwnerInit(owner), ]); - var label = building.TraitOrDefault(); + var label = building.TraitOrDefault(); if (label != null) label.Label = FileLabel(entry); placed[entry.Path] = building; @@ -693,11 +693,11 @@ string FileActorForRole(string role) { switch (role) { - case "test": return "clanker.file.test"; - case "config": return "clanker.file.config"; - case "manifest": return "clanker.file.manifest"; - case "docs": return "clanker.file.docs"; - case "build": return "clanker.file.build"; + case "test": return "combobulate.file.test"; + case "config": return "combobulate.file.config"; + case "manifest": return "combobulate.file.manifest"; + case "docs": return "combobulate.file.docs"; + case "build": return "combobulate.file.build"; case "source": return info.FileActors[0]; default: return info.FileActors[Math.Min(1, info.FileActors.Length - 1)]; } @@ -772,7 +772,7 @@ void ApplyAgents(World w, List snapshots) agents[snap.Id] = unit; agentHome[snap.Id] = home; agentTarget[snap.Id] = home; - agentLabels[snap.Id] = unit.TraitOrDefault(); + agentLabels[snap.Id] = unit.TraitOrDefault(); } if (!unit.IsInWorld) @@ -980,10 +980,10 @@ public void SendComposed(string text) if (boundId == AllTerminals) { foreach (var id in TerminalIds) - ClankerBackend.Post("/agent/ask", new { terminal = id, text }); + CombobulateBackend.Post("/agent/ask", new { terminal = id, text }); } else if (!string.IsNullOrEmpty(boundId)) - ClankerBackend.Post("/agent/ask", new { terminal = boundId, text }); + CombobulateBackend.Post("/agent/ask", new { terminal = boundId, text }); } // Queue raw keystrokes for the selected terminal's PTY (e.g. "\r", "\x03"). @@ -1069,7 +1069,7 @@ void ParseGrid(string json) foreach (var l in linesEl.EnumerateArray()) lines[i++] = l.GetString() ?? ""; - termGrid = new ClankerTermGrid + termGrid = new CombobulateTermGrid { Cols = root.GetProperty("cols").GetInt32(), Rows = root.GetProperty("rows").GetInt32(), diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerBuiltTerminal.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateBuiltTerminal.cs similarity index 54% rename from command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerBuiltTerminal.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateBuiltTerminal.cs index 8cd9e07..9c3968d 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerBuiltTerminal.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateBuiltTerminal.cs @@ -1,31 +1,31 @@ using OpenRA.Traits; -namespace OpenRA.Mods.Clanker.Traits +namespace OpenRA.Mods.Combobulate.Traits { [Desc("On a player-built Terminal building, asks the backend to create a", "terminal and claims the returned id so this building becomes that", "terminal's island. Bridge-spawned islands already carry an id and are", "left alone.")] - public class ClankerBuiltTerminalInfo : TraitInfo, Requires + public class CombobulateBuiltTerminalInfo : TraitInfo, Requires { - public override object Create(ActorInitializer init) { return new ClankerBuiltTerminal(); } + public override object Create(ActorInitializer init) { return new CombobulateBuiltTerminal(); } } - public class ClankerBuiltTerminal : INotifyAddedToWorld + public class CombobulateBuiltTerminal : INotifyAddedToWorld { void INotifyAddedToWorld.AddedToWorld(Actor self) { - var termRef = self.Trait(); + var termRef = self.Trait(); if (!string.IsNullOrEmpty(termRef.TerminalId)) return; - ClankerBackend.PostForId("/term/new", new { cols = 80, rows = 24 }, id => + CombobulateBackend.PostForId("/term/new", new { cols = 80, rows = 24 }, id => { if (!self.IsInWorld) return; termRef.TerminalId = id; - self.World.WorldActor.TraitOrDefault()?.RegisterPlayerTerminal(id, self); + self.World.WorldActor.TraitOrDefault()?.RegisterPlayerTerminal(id, self); }); } } diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerLabel.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateLabel.cs similarity index 76% rename from command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerLabel.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateLabel.cs index 0a305fd..6754b58 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerLabel.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateLabel.cs @@ -5,18 +5,18 @@ using OpenRA.Primitives; using OpenRA.Traits; -namespace OpenRA.Mods.Clanker.Traits +namespace OpenRA.Mods.Combobulate.Traits { - [Desc("Floating text over a clanker agent unit, set at runtime by ClankerBridge", + [Desc("Floating text over a combobulate agent unit, set at runtime by CombobulateBridge", "to show what the agent is doing right now (READ / WRITE / RUN).")] - public class ClankerLabelInfo : WithDecorationBaseInfo + public class CombobulateLabelInfo : WithDecorationBaseInfo { public readonly string Font = "TinyBold"; [Desc("Text colour.")] public readonly Color Color = Color.White; - public override object Create(ActorInitializer init) { return new ClankerLabel(init.Self, this); } + public override object Create(ActorInitializer init) { return new CombobulateLabel(init.Self, this); } public override void RulesetLoaded(Ruleset rules, ActorInfo ai) { @@ -27,11 +27,11 @@ public override void RulesetLoaded(Ruleset rules, ActorInfo ai) } } - public class ClankerLabel : WithDecorationBase + public class CombobulateLabel : WithDecorationBase { readonly SpriteFont font; - // Written by ClankerBridge on the game thread; read here when rendering. + // Written by CombobulateBridge on the game thread; read here when rendering. // A torn read of a string reference is harmless, so no synchronization. public string Label = ""; @@ -39,7 +39,7 @@ public class ClankerLabel : WithDecorationBase // as it fills); falls back to the actor's configured colour when null. public Color? LabelColor = null; - public ClankerLabel(Actor self, ClankerLabelInfo info) + public CombobulateLabel(Actor self, CombobulateLabelInfo info) : base(self, info) { font = Game.Renderer.Fonts[info.Font]; diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerSidebarLoader.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateSidebarLoader.cs similarity index 60% rename from command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerSidebarLoader.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateSidebarLoader.cs index fa0c5d9..0860cb3 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerSidebarLoader.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateSidebarLoader.cs @@ -2,23 +2,23 @@ using OpenRA.Traits; using OpenRA.Widgets; -namespace OpenRA.Mods.Clanker.Traits +namespace OpenRA.Mods.Combobulate.Traits { [TraitLocation(SystemActors.World)] - [Desc("Loads the Command & Clanker interactive terminal panel into the ingame UI when a game starts.")] - public class ClankerSidebarLoaderInfo : TraitInfo + [Desc("Loads the Command & Combobulate interactive terminal panel into the ingame UI when a game starts.")] + public class CombobulateSidebarLoaderInfo : TraitInfo { [Desc("Interactive terminal panel to load into the UI root.")] - public readonly string TerminalWidget = "CLANKER_TERMINAL"; + public readonly string TerminalWidget = "COMBOBULATE_TERMINAL"; - public override object Create(ActorInitializer init) { return new ClankerSidebarLoader(this); } + public override object Create(ActorInitializer init) { return new CombobulateSidebarLoader(this); } } - public class ClankerSidebarLoader : IWorldLoaded + public class CombobulateSidebarLoader : IWorldLoaded { - readonly ClankerSidebarLoaderInfo info; + readonly CombobulateSidebarLoaderInfo info; - public ClankerSidebarLoader(ClankerSidebarLoaderInfo info) + public CombobulateSidebarLoader(CombobulateSidebarLoaderInfo info) { this.info = info; } diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerTermGrid.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateTermGrid.cs similarity index 84% rename from command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerTermGrid.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateTermGrid.cs index 2b10883..3d5e080 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerTermGrid.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateTermGrid.cs @@ -1,9 +1,9 @@ -namespace OpenRA.Mods.Clanker.Traits +namespace OpenRA.Mods.Combobulate.Traits { // An immutable snapshot of a terminal's resolved screen, produced by the // bridge from /termview frames and read by the terminal widget. Replaced // wholesale on each frame so readers never see a half-updated grid. - public sealed class ClankerTermGrid + public sealed class CombobulateTermGrid { public string[] Lines { get; init; } = System.Array.Empty(); public int Cols { get; init; } diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerTerminalRef.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateTerminalRef.cs similarity index 58% rename from command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerTerminalRef.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateTerminalRef.cs index 44aa1e3..38cb669 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Traits/ClankerTerminalRef.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Traits/CombobulateTerminalRef.cs @@ -1,34 +1,34 @@ using System.Collections.Generic; using OpenRA.Traits; -namespace OpenRA.Mods.Clanker.Traits +namespace OpenRA.Mods.Combobulate.Traits { [Desc("Marks a terminal-island building with its backend terminal id and the", "agent's recent action log, so the sidebar can read them when it is selected.")] - public class ClankerTerminalRefInfo : TraitInfo + public class CombobulateTerminalRefInfo : TraitInfo { - public override object Create(ActorInitializer init) { return new ClankerTerminalRef(init); } + public override object Create(ActorInitializer init) { return new CombobulateTerminalRef(init); } } - public class ClankerTerminalRef + public class CombobulateTerminalRef { // Settable so a player-built Terminal can claim its id after the backend // assigns one; bridge-spawned islands get it from the init. public string TerminalId { get; set; } - // Set by ClankerBridge on the game thread; read by the sidebar logic. + // Set by CombobulateBridge on the game thread; read by the sidebar logic. public IReadOnlyList Recent = new List(); // A short description of what the agent is doing right now (or "idle"). public string Activity = "idle"; - public ClankerTerminalRef(ActorInitializer init) + public CombobulateTerminalRef(ActorInitializer init) { - TerminalId = init.GetValue(""); + TerminalId = init.GetValue(""); } } - public class ClankerTerminalRefInit(string value) : ValueActorInit(value), ISingleInstanceInit + public class CombobulateTerminalRefInit(string value) : ValueActorInit(value), ISingleInstanceInit { } } diff --git a/command-and-clanker/OpenRA.Mods.Clanker/UtilityCommands/CreateCanvasMapCommand.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/UtilityCommands/CreateCanvasMapCommand.cs similarity index 86% rename from command-and-clanker/OpenRA.Mods.Clanker/UtilityCommands/CreateCanvasMapCommand.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/UtilityCommands/CreateCanvasMapCommand.cs index e434d84..de93f13 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/UtilityCommands/CreateCanvasMapCommand.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/UtilityCommands/CreateCanvasMapCommand.cs @@ -3,9 +3,9 @@ using OpenRA.FileSystem; using OpenRA.Primitives; -namespace OpenRA.Mods.Clanker.UtilityCommands +namespace OpenRA.Mods.Combobulate.UtilityCommands { - // One-shot generator for the Command & Clanker canvas: a flat, open map made + // One-shot generator for the Command & Combobulate canvas: a flat, open map made // entirely of clear terrain, so the live world (islands, walled folders, and // agent units) sits on ground we control instead of fighting an RA map's // pre-built walls, water, and ore. @@ -19,7 +19,7 @@ bool IUtilityCommand.ValidateArguments(string[] args) } [Desc("OUTPUTDIR [SIZE]", - "Create a flat, open Command & Clanker canvas map (all clear terrain) at OUTPUTDIR.")] + "Create a flat, open Command & Combobulate canvas map (all clear terrain) at OUTPUTDIR.")] void IUtilityCommand.Run(Utility utility, string[] args) { // PlayerReference's default Color reads Game.ModData, so it must be set. @@ -31,8 +31,8 @@ void IUtilityCommand.Run(Utility utility, string[] args) var map = new Map(modData, terrain, new Size(size + 2, size + maxHeight + 2)) { - Title = "Clanker Canvas", - Author = "Command & Clanker", + Title = "Combobulate Canvas", + Author = "Command & Combobulate", RequiresMod = modData.Manifest.Id, }; diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Widgets/ClankerTerminalWidget.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/CombobulateTerminalWidget.cs similarity index 89% rename from command-and-clanker/OpenRA.Mods.Clanker/Widgets/ClankerTerminalWidget.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/CombobulateTerminalWidget.cs index 38651da..2f2559b 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Widgets/ClankerTerminalWidget.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/CombobulateTerminalWidget.cs @@ -1,34 +1,34 @@ using System; -using OpenRA.Mods.Clanker.Traits; +using OpenRA.Mods.Combobulate.Traits; using OpenRA.Mods.Common.Widgets; using OpenRA.Primitives; using OpenRA.Widgets; -namespace OpenRA.Mods.Clanker.Widgets +namespace OpenRA.Mods.Combobulate.Widgets { // A live, interactive terminal view. The backend resolves the PTY into a - // screen grid (see ClankerBridge.TerminalGrid); this widget paints each cell + // screen grid (see CombobulateBridge.TerminalGrid); this widget paints each cell // at a fixed advance and forwards keystrokes back to the PTY. It is invisible // until a terminal island is selected, and follows the selection itself. // // The cell size is measured from the font: for a monospace font every glyph // advance is identical, so column positions stay perfectly aligned. - public class ClankerTerminalWidget : Widget + public class CombobulateTerminalWidget : Widget { - public readonly string Font = "ClankerTerm"; + public readonly string Font = "CombobulateTerm"; public readonly int LineGap = 2; public readonly int Padding = 6; public readonly Color Background = Color.FromArgb(235, 12, 14, 16); public readonly Color Foreground = Color.FromArgb(220, 220, 220); - readonly ClankerBridge bridge; + readonly CombobulateBridge bridge; int lastResizeCols; int lastResizeRows; [ObjectCreator.UseCtor] - public ClankerTerminalWidget(World world) + public CombobulateTerminalWidget(World world) { - bridge = world.WorldActor.TraitOrDefault(); + bridge = world.WorldActor.TraitOrDefault(); } // Pixel size of one character cell, taken from the font's own metrics. @@ -44,7 +44,7 @@ public override void Tick() if (bridge == null) return; - // The panel binding is driven by ClankerTerminalLogic; here we only keep + // The panel binding is driven by CombobulateTerminalLogic; here we only keep // the streamed PTY sized to the grid. With no streamed terminal (the // panel is dismissed or showing the All view) there is nothing to size. if (string.IsNullOrEmpty(bridge.StreamedTerminal)) @@ -85,7 +85,7 @@ public override void Draw() var oy = rb.Y + Padding; // The All view has no single PTY to mirror; show what the composer targets. - if (bridge.BoundTerminal == ClankerBridge.AllTerminals) + if (bridge.BoundTerminal == CombobulateBridge.AllTerminals) { font.DrawTextWithContrast( $"All terminals — input broadcasts to {bridge.TerminalIds.Count} agent(s)", diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Widgets/Logic/ClankerMenuLogic.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/Logic/CombobulateMenuLogic.cs similarity index 58% rename from command-and-clanker/OpenRA.Mods.Clanker/Widgets/Logic/ClankerMenuLogic.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/Logic/CombobulateMenuLogic.cs index 5a50edc..f4ea0a3 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Widgets/Logic/ClankerMenuLogic.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/Logic/CombobulateMenuLogic.cs @@ -1,17 +1,17 @@ using OpenRA.Mods.Common.Widgets; using OpenRA.Widgets; -namespace OpenRA.Mods.Clanker.Widgets.Logic +namespace OpenRA.Mods.Combobulate.Widgets.Logic { - // The Command & Clanker shell menu: one button that boots straight into the + // The Command & Combobulate shell menu: one button that boots straight into the // canvas map (no lobby), plus Quit. Replaces the stock main menu via the // world's LoadWidgetAtGameStart.ShellmapRoot override. - public class ClankerMenuLogic : ChromeLogic + public class CombobulateMenuLogic : ChromeLogic { [ObjectCreator.UseCtor] - public ClankerMenuLogic(Widget widget) + public CombobulateMenuLogic(Widget widget) { - widget.Get("LAUNCH").OnClick = () => Game.LoadMap("clanker-canvas"); + widget.Get("LAUNCH").OnClick = () => Game.LoadMap("combobulate-canvas"); widget.Get("QUIT").OnClick = Game.Exit; } } diff --git a/command-and-clanker/OpenRA.Mods.Clanker/Widgets/Logic/ClankerTerminalLogic.cs b/command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/Logic/CombobulateTerminalLogic.cs similarity index 81% rename from command-and-clanker/OpenRA.Mods.Clanker/Widgets/Logic/ClankerTerminalLogic.cs rename to command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/Logic/CombobulateTerminalLogic.cs index 547c3b7..851eaa5 100644 --- a/command-and-clanker/OpenRA.Mods.Clanker/Widgets/Logic/ClankerTerminalLogic.cs +++ b/command-and-combobulate/OpenRA.Mods.Combobulate/Widgets/Logic/CombobulateTerminalLogic.cs @@ -1,26 +1,26 @@ -using OpenRA.Mods.Clanker.Traits; +using OpenRA.Mods.Combobulate.Traits; using OpenRA.Mods.Common.Widgets; using OpenRA.Widgets; -namespace OpenRA.Mods.Clanker.Widgets.Logic +namespace OpenRA.Mods.Combobulate.Widgets.Logic { // Wires the native-chrome controls around the terminal grid: a button that // cycles which terminal the panel mirrors (t1 -> ... -> All), a composer that // sends a typed line to the bound agent(s), and a close button that dismisses - // the panel. The grid itself is painted by ClankerTerminalWidget; this logic + // the panel. The grid itself is painted by CombobulateTerminalWidget; this logic // only drives the chrome and reconciles it with the map selection. - public class ClankerTerminalLogic : ChromeLogic + public class CombobulateTerminalLogic : ChromeLogic { readonly World world; - readonly ClankerBridge bridge; + readonly CombobulateBridge bridge; readonly Widget panel; string lastSelection; [ObjectCreator.UseCtor] - public ClankerTerminalLogic(Widget widget, World world) + public CombobulateTerminalLogic(Widget widget, World world) { this.world = world; - bridge = world.WorldActor.TraitOrDefault(); + bridge = world.WorldActor.TraitOrDefault(); panel = widget.Get("PANEL"); @@ -31,7 +31,7 @@ public ClankerTerminalLogic(Widget widget, World world) if (string.IsNullOrEmpty(bound)) return "—"; - return bound == ClankerBridge.AllTerminals ? "All" : bound; + return bound == CombobulateBridge.AllTerminals ? "All" : bound; }; mode.OnClick = () => bridge?.CycleBoundTerminal(); @@ -91,7 +91,7 @@ string SelectedTerminal() if (!a.IsInWorld) continue; - var r = a.TraitOrDefault(); + var r = a.TraitOrDefault(); if (r != null) return r.TerminalId; } diff --git a/command-and-clanker/fetch-engine.sh b/command-and-combobulate/fetch-engine.sh similarity index 100% rename from command-and-clanker/fetch-engine.sh rename to command-and-combobulate/fetch-engine.sh diff --git a/command-and-clanker/launch-dedicated.cmd b/command-and-combobulate/launch-dedicated.cmd similarity index 100% rename from command-and-clanker/launch-dedicated.cmd rename to command-and-combobulate/launch-dedicated.cmd diff --git a/command-and-clanker/launch-dedicated.sh b/command-and-combobulate/launch-dedicated.sh similarity index 100% rename from command-and-clanker/launch-dedicated.sh rename to command-and-combobulate/launch-dedicated.sh diff --git a/command-and-clanker/launch-game.cmd b/command-and-combobulate/launch-game.cmd similarity index 100% rename from command-and-clanker/launch-game.cmd rename to command-and-combobulate/launch-game.cmd diff --git a/command-and-clanker/launch-game.sh b/command-and-combobulate/launch-game.sh similarity index 100% rename from command-and-clanker/launch-game.sh rename to command-and-combobulate/launch-game.sh diff --git a/command-and-clanker/make.cmd b/command-and-combobulate/make.cmd similarity index 100% rename from command-and-clanker/make.cmd rename to command-and-combobulate/make.cmd diff --git a/command-and-clanker/make.ps1 b/command-and-combobulate/make.ps1 similarity index 100% rename from command-and-clanker/make.ps1 rename to command-and-combobulate/make.ps1 diff --git a/command-and-clanker/mod.config b/command-and-combobulate/mod.config similarity index 97% rename from command-and-clanker/mod.config rename to command-and-combobulate/mod.config index 35351c3..7082731 100644 --- a/command-and-clanker/mod.config +++ b/command-and-combobulate/mod.config @@ -6,7 +6,7 @@ # The id of the mod packaged by this project. # This must exist as a directory in the mods directory and should not contain spaces. -MOD_ID="clanker" +MOD_ID="combobulate" # The OpenRA engine version to use for this project. ENGINE_VERSION="playtest-20260222" @@ -21,7 +21,7 @@ ENGINE_VERSION="playtest-20260222" # - Windows installers will be named as {PACKAGING_INSTALLER_NAME}-{TAG}.exe # - macOS installers will be named as {PACKAGING_INSTALLER_NAME}-{TAG}.dmg # - Linux .appimages will be named as {PACKAGING_INSTALLER_NAME}-${TAG}.AppImage -PACKAGING_INSTALLER_NAME="CommandAndClanker" +PACKAGING_INSTALLER_NAME="CommandAndCombobulate" # The human-readable name for this project. # This is used in: @@ -35,7 +35,7 @@ PACKAGING_INSTALLER_NAME="CommandAndClanker" # - Windows desktop shortcut # - Windows "Programs and Features" list # - Linux launcher shortcut -PACKAGING_DISPLAY_NAME="Command & Clanker" +PACKAGING_DISPLAY_NAME="Command & Combobulate" # The URL for the project homepage. # This is used in: diff --git a/command-and-clanker/mods/clanker/chrome/clanker-mainmenu.yaml b/command-and-combobulate/mods/combobulate/chrome/combobulate-mainmenu.yaml similarity index 76% rename from command-and-clanker/mods/clanker/chrome/clanker-mainmenu.yaml rename to command-and-combobulate/mods/combobulate/chrome/combobulate-mainmenu.yaml index 4681a78..1871bce 100644 --- a/command-and-clanker/mods/clanker/chrome/clanker-mainmenu.yaml +++ b/command-and-combobulate/mods/combobulate/chrome/combobulate-mainmenu.yaml @@ -1,5 +1,5 @@ -Container@CLANKER_MAINMENU: - Logic: ClankerMenuLogic +Container@COMBOBULATE_MAINMENU: + Logic: CombobulateMenuLogic Width: WINDOW_WIDTH Height: WINDOW_HEIGHT Children: @@ -17,17 +17,17 @@ Container@CLANKER_MAINMENU: Height: 30 Font: BigBold Align: Center - Text: clanker-mod-title + Text: combobulate-mod-title Button@LAUNCH: X: (PARENT_WIDTH - WIDTH) / 2 Y: 96 Width: 280 Height: 44 Font: Bold - Text: button-clanker-launch + Text: button-combobulate-launch Button@QUIT: X: (PARENT_WIDTH - WIDTH) / 2 Y: 152 Width: 280 Height: 34 - Text: button-clanker-quit + Text: button-combobulate-quit diff --git a/command-and-clanker/mods/clanker/chrome/clanker-terminal.yaml b/command-and-combobulate/mods/combobulate/chrome/combobulate-terminal.yaml similarity index 85% rename from command-and-clanker/mods/clanker/chrome/clanker-terminal.yaml rename to command-and-combobulate/mods/combobulate/chrome/combobulate-terminal.yaml index 47cad87..d8b1b14 100644 --- a/command-and-clanker/mods/clanker/chrome/clanker-terminal.yaml +++ b/command-and-combobulate/mods/combobulate/chrome/combobulate-terminal.yaml @@ -1,5 +1,5 @@ -Container@CLANKER_TERMINAL: - Logic: ClankerTerminalLogic +Container@COMBOBULATE_TERMINAL: + Logic: CombobulateTerminalLogic X: 12 Y: WINDOW_HEIGHT - HEIGHT - 12 Width: 732 @@ -10,12 +10,12 @@ Container@CLANKER_TERMINAL: Height: PARENT_HEIGHT Background: dialog Children: - ClankerTerminal@GRID: + CombobulateTerminal@GRID: X: 9 Y: 9 Width: PARENT_WIDTH - 18 Height: PARENT_HEIGHT - 52 - Font: ClankerTerm + Font: CombobulateTerm Padding: 6 LineGap: 2 Button@TERM_MODE: diff --git a/command-and-combobulate/mods/combobulate/fluent/combobulate.ftl b/command-and-combobulate/mods/combobulate/fluent/combobulate.ftl new file mode 100644 index 0000000..6fda983 --- /dev/null +++ b/command-and-combobulate/mods/combobulate/fluent/combobulate.ftl @@ -0,0 +1,8 @@ +combobulate-mod-title = Command & Combobulate +combobulate-mod-windowtitle = Command & Combobulate +loadscreen-loading = Comboluating..., Summoning subagents..., Compacting context..., Warming the prompt cache..., Reticulating splines..., Negotiating with the rate limiter..., Spinning up PTYs..., Aligning the combobulates..., Tokenizing the vibes..., Deploying robots... +button-combobulate-launch = Start Combobulating +button-combobulate-quit = Quit +actor-combobulate-terminal = + .name = Terminal + .description = Spawns a Command & Combobulate agent terminal. diff --git a/command-and-clanker/mods/clanker/fonts/DejaVuSansMono.ttf b/command-and-combobulate/mods/combobulate/fonts/DejaVuSansMono.ttf similarity index 100% rename from command-and-clanker/mods/clanker/fonts/DejaVuSansMono.ttf rename to command-and-combobulate/mods/combobulate/fonts/DejaVuSansMono.ttf diff --git a/command-and-clanker/mods/clanker/maps/clanker-canvas/map.bin b/command-and-combobulate/mods/combobulate/maps/combobulate-canvas/map.bin similarity index 100% rename from command-and-clanker/mods/clanker/maps/clanker-canvas/map.bin rename to command-and-combobulate/mods/combobulate/maps/combobulate-canvas/map.bin diff --git a/command-and-clanker/mods/clanker/maps/clanker-canvas/map.png b/command-and-combobulate/mods/combobulate/maps/combobulate-canvas/map.png similarity index 100% rename from command-and-clanker/mods/clanker/maps/clanker-canvas/map.png rename to command-and-combobulate/mods/combobulate/maps/combobulate-canvas/map.png diff --git a/command-and-clanker/mods/clanker/maps/clanker-canvas/map.yaml b/command-and-combobulate/mods/combobulate/maps/combobulate-canvas/map.yaml similarity index 94% rename from command-and-clanker/mods/clanker/maps/clanker-canvas/map.yaml rename to command-and-combobulate/mods/combobulate/maps/combobulate-canvas/map.yaml index 8486c4c..3b5e830 100644 --- a/command-and-clanker/mods/clanker/maps/clanker-canvas/map.yaml +++ b/command-and-combobulate/mods/combobulate/maps/combobulate-canvas/map.yaml @@ -1,10 +1,10 @@ MapFormat: 12 -RequiresMod: clanker +RequiresMod: combobulate -Title: Clanker Canvas +Title: Combobulate Canvas -Author: Command & Clanker +Author: Command & Combobulate Tileset: TEMPERAT diff --git a/command-and-clanker/mods/clanker/mod.yaml b/command-and-combobulate/mods/combobulate/mod.yaml similarity index 92% rename from command-and-clanker/mods/clanker/mod.yaml rename to command-and-combobulate/mods/combobulate/mod.yaml index 293d3cd..b863150 100644 --- a/command-and-clanker/mods/clanker/mod.yaml +++ b/command-and-combobulate/mods/combobulate/mod.yaml @@ -1,9 +1,9 @@ Metadata: - Title: clanker-mod-title + Title: combobulate-mod-title Version: 0.0.1 Website: https://www.openra.net WebIcon32: https://www.openra.net/images/icons/ra_32x32.png - WindowTitle: clanker-mod-windowtitle + WindowTitle: combobulate-mod-windowtitle PackageFormats: Mix @@ -11,7 +11,7 @@ FileSystem: ContentInstallerFileSystem SystemPackages: ^EngineDir ^EngineDir|mods/ra: ra - $clanker: clanker + $combobulate: combobulate ^EngineDir|mods/common: common ~^SupportDir|Content/ra/v2/: content common|scripts @@ -68,7 +68,7 @@ FileSystem: ContentInstallerFileSystem ContentInstallerMod: ra-content MapFolders: - clanker|maps: System + combobulate|maps: System ra|maps: System ~^SupportDir|maps/ra/{DEV_VERSION}: User @@ -89,8 +89,8 @@ Rules: ra|rules/ships.yaml ra|rules/fakes.yaml ra|rules/map-generators.yaml - clanker|rules/world.yaml - clanker|rules/actors.yaml + combobulate|rules/world.yaml + combobulate|rules/actors.yaml Sequences: ra|sequences/ships.yaml @@ -113,7 +113,7 @@ Cursors: Chrome: ra|chrome.yaml -Assemblies: OpenRA.Mods.Common.dll, OpenRA.Mods.Cnc.dll, OpenRA.Mods.Clanker.dll +Assemblies: OpenRA.Mods.Common.dll, OpenRA.Mods.Cnc.dll, OpenRA.Mods.Combobulate.dll ChromeLayout: common|chrome/ingame.yaml @@ -170,8 +170,8 @@ ChromeLayout: common|chrome/editor.yaml common|chrome/playerprofile.yaml common|chrome/text-notifications.yaml - clanker|chrome/clanker-terminal.yaml - clanker|chrome/clanker-mainmenu.yaml + combobulate|chrome/combobulate-terminal.yaml + combobulate|chrome/combobulate-mainmenu.yaml FluentMessages: common|fluent/common.ftl @@ -182,7 +182,7 @@ FluentMessages: ra|fluent/chrome.ftl ra|fluent/hotkeys.ftl ra|fluent/rules.ftl - clanker|fluent/clanker.ftl + combobulate|fluent/combobulate.ftl AllowUnusedFluentMessagesInExternalPackages: true @@ -214,10 +214,10 @@ Hotkeys: common|hotkeys/control-groups.yaml ra|hotkeys.yaml -LoadScreen: ClankerLoadScreen - Image: clanker|uibits/clanker-loadscreen.png - Image2x: clanker|uibits/clanker-loadscreen-2x.png - Image3x: clanker|uibits/clanker-loadscreen-3x.png +LoadScreen: CombobulateLoadScreen + Image: combobulate|uibits/combobulate-loadscreen.png + Image2x: combobulate|uibits/combobulate-loadscreen-2x.png + Image3x: combobulate|uibits/combobulate-loadscreen-3x.png ServerTraits: LobbyCommands @@ -262,8 +262,8 @@ Fonts: Font: ra|ZoodRangmah.ttf Size: 48 Ascender: 26 - ClankerTerm: - Font: clanker|fonts/DejaVuSansMono.ttf + CombobulateTerm: + Font: combobulate|fonts/DejaVuSansMono.ttf Size: 14 Ascender: 11 diff --git a/command-and-clanker/mods/clanker/rules/actors.yaml b/command-and-combobulate/mods/combobulate/rules/actors.yaml similarity index 83% rename from command-and-clanker/mods/clanker/rules/actors.yaml rename to command-and-combobulate/mods/combobulate/rules/actors.yaml index 33c56db..5ac13dc 100644 --- a/command-and-clanker/mods/clanker/rules/actors.yaml +++ b/command-and-combobulate/mods/combobulate/rules/actors.yaml @@ -1,7 +1,7 @@ -clanker.terminal: +combobulate.terminal: Inherits: PDOX # RenderSprites.Image defaults to the actor name, so without this override - # the engine looks for sequences under `clanker.terminal` instead of `pdox` + # the engine looks for sequences under `combobulate.terminal` instead of `pdox` # and the production palette crashes refreshing the cameo. RenderSprites: Image: pdox @@ -12,11 +12,11 @@ clanker.terminal: # is always available and uncapped. Prerequisites: ~techlevel.infonly BuildLimit: 0 - Description: actor-clanker-terminal.description + Description: actor-combobulate-terminal.description Valued: Cost: 100 Tooltip: - Name: actor-clanker-terminal.name + Name: actor-combobulate-terminal.name # PDOX draws -200 power and hosts the Chronosphere superweapon. Strip both # so the Terminal is a plain building. Power: @@ -28,28 +28,28 @@ clanker.terminal: -ProvidesPrerequisite@germanstructure: -ProvidesPrerequisite@buildingname: -MustBeDestroyed: - ClankerTerminalRef: - ClankerBuiltTerminal: + CombobulateTerminalRef: + CombobulateBuiltTerminal: # Context-window readout over the terminal; the bridge sets the text and # reddens it as the agent's context fills (the base browns out). - ClankerLabel: + CombobulateLabel: Font: Bold Position: Top ValidRelationships: Ally, Neutral, Enemy Color: 9EE6A0 -clanker.folderwall: +combobulate.folderwall: Inherits: SBAG RenderSprites: Image: sbag Interactable: - ClankerLabel: + CombobulateLabel: Font: Bold Position: Top ValidRelationships: Ally, Neutral, Enemy Color: FFFFAA -clanker.agent: +combobulate.agent: Inherits: HELI RenderSprites: Image: heli @@ -62,106 +62,106 @@ clanker.agent: -Buildable: Aircraft: Speed: 170 - ClankerLabel: + CombobulateLabel: Position: Top ValidRelationships: Ally, Neutral, Enemy Color: FFE066 -clanker.agent.codex: +combobulate.agent.codex: Inherits: ARTY RenderSprites: Image: arty Mobile: Speed: 170 - ClankerLabel: + CombobulateLabel: Position: Top ValidRelationships: Ally, Neutral, Enemy Color: FF99CC -clanker.subagent: +combobulate.subagent: Inherits: E1 RenderSprites: Image: e1 Mobile: Speed: 120 - ClankerLabel: + CombobulateLabel: Position: Top ValidRelationships: Ally, Neutral, Enemy Color: FFE066 # One small civilian house per touched file. The label (file name + size) shows # only while the house is selected, so the commander clicks one to inspect it. -clanker.file1: +combobulate.file1: Inherits: V05 RenderSprites: Image: v05 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file2: +combobulate.file2: Inherits: V06 RenderSprites: Image: v06 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file3: +combobulate.file3: Inherits: V07 RenderSprites: Image: v07 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file4: +combobulate.file4: Inherits: V08 RenderSprites: Image: v08 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file5: +combobulate.file5: Inherits: V09 RenderSprites: Image: v09 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file6: +combobulate.file6: Inherits: V10 RenderSprites: Image: v10 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file7: +combobulate.file7: Inherits: V11 RenderSprites: Image: v11 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true @@ -173,68 +173,68 @@ clanker.file7: # radar dome for docs, a silo for build output. They are spawned as inert # neutral decorations: Buildable is dropped (no production here) and Power is # zeroed so they do not perturb a power grid. -clanker.file.test: +combobulate.file.test: Inherits: TENT RenderSprites: Image: tent -Buildable: - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file.config: +combobulate.file.config: Inherits: POWR RenderSprites: Image: powr -Buildable: Power: Amount: 0 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file.manifest: +combobulate.file.manifest: Inherits: ATEK RenderSprites: Image: atek -Buildable: Power: Amount: 0 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file.docs: +combobulate.file.docs: Inherits: DOME RenderSprites: Image: dome -Buildable: Power: Amount: 0 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true ValidRelationships: Ally, Neutral, Enemy Color: FFFFFF -clanker.file.build: +combobulate.file.build: Inherits: SILO RenderSprites: Image: silo -Buildable: Power: Amount: 0 - ClankerLabel: + CombobulateLabel: Font: TinyBold Position: Top RequiresSelection: true diff --git a/command-and-combobulate/mods/combobulate/rules/world.yaml b/command-and-combobulate/mods/combobulate/rules/world.yaml new file mode 100644 index 0000000..3c15116 --- /dev/null +++ b/command-and-combobulate/mods/combobulate/rules/world.yaml @@ -0,0 +1,7 @@ +World: + CombobulateBridge: + CombobulateSidebarLoader: + LoadWidgetAtGameStart: + ShellmapRoot: COMBOBULATE_MAINMENU + MapOptions: + TechLevel: unrestricted diff --git a/command-and-clanker/mods/clanker/uibits/README.md b/command-and-combobulate/mods/combobulate/uibits/README.md similarity index 75% rename from command-and-clanker/mods/clanker/uibits/README.md rename to command-and-combobulate/mods/combobulate/uibits/README.md index ba5d22d..97d1cf3 100644 --- a/command-and-clanker/mods/clanker/uibits/README.md +++ b/command-and-combobulate/mods/combobulate/uibits/README.md @@ -6,8 +6,8 @@ below and the game picks them up on next launch — no code changes needed. ## Load screen (banner logo) A centered banner on the loading screen (dark background + animated stripe + the loading phrases). Wide 2:1 banner, PNG, transparent or dark background. -- `clanker-loadscreen.png` — 512x256 -- `clanker-loadscreen-2x.png` — 1024x512 -- `clanker-loadscreen-3x.png` — 2048x1024 +- `combobulate-loadscreen.png` — 512x256 +- `combobulate-loadscreen-2x.png` — 1024x512 +- `combobulate-loadscreen-3x.png` — 2048x1024 (The committed files are dark placeholders; overwrite them with real art.) diff --git a/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen-2x.png b/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen-2x.png new file mode 100644 index 0000000..ab8606f Binary files /dev/null and b/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen-2x.png differ diff --git a/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen-3x.png b/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen-3x.png new file mode 100644 index 0000000..53123e1 Binary files /dev/null and b/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen-3x.png differ diff --git a/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen.png b/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen.png new file mode 100644 index 0000000..a2af692 Binary files /dev/null and b/command-and-combobulate/mods/combobulate/uibits/combobulate-loadscreen.png differ diff --git a/command-and-clanker/omnisharp.json b/command-and-combobulate/omnisharp.json similarity index 100% rename from command-and-clanker/omnisharp.json rename to command-and-combobulate/omnisharp.json diff --git a/command-and-combobulate/package.json b/command-and-combobulate/package.json new file mode 100644 index 0000000..8b1413b --- /dev/null +++ b/command-and-combobulate/package.json @@ -0,0 +1,12 @@ +{ + "name": "command-and-combobulate-mod", + "version": "0.1.0", + "private": true, + "description": "Command & Combobulate OpenRA mod (built on the OpenRA Mod SDK).", + "scripts": { + "build": "make", + "launch": "./launch-game.sh", + "game": "make && ./launch-game.sh", + "utility": "./utility.sh combobulate" + } +} diff --git a/command-and-clanker/packaging/artwork/icon_1024x1024.png b/command-and-combobulate/packaging/artwork/icon_1024x1024.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_1024x1024.png rename to command-and-combobulate/packaging/artwork/icon_1024x1024.png diff --git a/command-and-clanker/packaging/artwork/icon_128x128.png b/command-and-combobulate/packaging/artwork/icon_128x128.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_128x128.png rename to command-and-combobulate/packaging/artwork/icon_128x128.png diff --git a/command-and-clanker/packaging/artwork/icon_16x16.png b/command-and-combobulate/packaging/artwork/icon_16x16.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_16x16.png rename to command-and-combobulate/packaging/artwork/icon_16x16.png diff --git a/command-and-clanker/packaging/artwork/icon_24x24.png b/command-and-combobulate/packaging/artwork/icon_24x24.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_24x24.png rename to command-and-combobulate/packaging/artwork/icon_24x24.png diff --git a/command-and-clanker/packaging/artwork/icon_256x256.png b/command-and-combobulate/packaging/artwork/icon_256x256.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_256x256.png rename to command-and-combobulate/packaging/artwork/icon_256x256.png diff --git a/command-and-clanker/packaging/artwork/icon_32x32.png b/command-and-combobulate/packaging/artwork/icon_32x32.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_32x32.png rename to command-and-combobulate/packaging/artwork/icon_32x32.png diff --git a/command-and-clanker/packaging/artwork/icon_48x48.png b/command-and-combobulate/packaging/artwork/icon_48x48.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_48x48.png rename to command-and-combobulate/packaging/artwork/icon_48x48.png diff --git a/command-and-clanker/packaging/artwork/icon_512x512.png b/command-and-combobulate/packaging/artwork/icon_512x512.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_512x512.png rename to command-and-combobulate/packaging/artwork/icon_512x512.png diff --git a/command-and-clanker/packaging/artwork/icon_64x64.png b/command-and-combobulate/packaging/artwork/icon_64x64.png similarity index 100% rename from command-and-clanker/packaging/artwork/icon_64x64.png rename to command-and-combobulate/packaging/artwork/icon_64x64.png diff --git a/command-and-clanker/packaging/artwork/macos-background-2x.png b/command-and-combobulate/packaging/artwork/macos-background-2x.png similarity index 100% rename from command-and-clanker/packaging/artwork/macos-background-2x.png rename to command-and-combobulate/packaging/artwork/macos-background-2x.png diff --git a/command-and-clanker/packaging/artwork/macos-background.png b/command-and-combobulate/packaging/artwork/macos-background.png similarity index 100% rename from command-and-clanker/packaging/artwork/macos-background.png rename to command-and-combobulate/packaging/artwork/macos-background.png diff --git a/command-and-clanker/packaging/functions.sh b/command-and-combobulate/packaging/functions.sh similarity index 100% rename from command-and-clanker/packaging/functions.sh rename to command-and-combobulate/packaging/functions.sh diff --git a/command-and-clanker/packaging/linux/buildpackage.sh b/command-and-combobulate/packaging/linux/buildpackage.sh similarity index 100% rename from command-and-clanker/packaging/linux/buildpackage.sh rename to command-and-combobulate/packaging/linux/buildpackage.sh diff --git a/command-and-clanker/packaging/macos/buildpackage.sh b/command-and-combobulate/packaging/macos/buildpackage.sh similarity index 100% rename from command-and-clanker/packaging/macos/buildpackage.sh rename to command-and-combobulate/packaging/macos/buildpackage.sh diff --git a/command-and-clanker/packaging/package-all.sh b/command-and-combobulate/packaging/package-all.sh similarity index 100% rename from command-and-clanker/packaging/package-all.sh rename to command-and-combobulate/packaging/package-all.sh diff --git a/command-and-clanker/packaging/windows/buildpackage.nsi b/command-and-combobulate/packaging/windows/buildpackage.nsi similarity index 100% rename from command-and-clanker/packaging/windows/buildpackage.nsi rename to command-and-combobulate/packaging/windows/buildpackage.nsi diff --git a/command-and-clanker/packaging/windows/buildpackage.sh b/command-and-combobulate/packaging/windows/buildpackage.sh similarity index 100% rename from command-and-clanker/packaging/windows/buildpackage.sh rename to command-and-combobulate/packaging/windows/buildpackage.sh diff --git a/command-and-clanker/utility.cmd b/command-and-combobulate/utility.cmd similarity index 100% rename from command-and-clanker/utility.cmd rename to command-and-combobulate/utility.cmd diff --git a/command-and-clanker/utility.sh b/command-and-combobulate/utility.sh similarity index 100% rename from command-and-clanker/utility.sh rename to command-and-combobulate/utility.sh diff --git a/docs/architecture.md b/docs/architecture.md index 0ebfb35..a73d3a9 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,37 +1,37 @@ # Architecture -Command & Clanker is two pieces: a Node **backend** that ingests agent activity and +Command & Combobulate is two pieces: a Node **backend** that ingests agent activity and owns the real terminals, and an **OpenRA mod** that renders that activity inside the OpenRA engine. The world is event-driven — agents report their tool calls; nothing scrapes `/proc`. ``` - Agent (Claude Code, Codex) in a Command & Clanker terminal + Agent (Claude Code, Codex) in a Command & Combobulate terminal | adapter POSTs tool calls / lifecycle events v Node backend (server/) - POST /ingest: normalize agent events -> agents + folder regions - world builder: terminal + folder regions (a directory forest) - - TerminalManager: real PTYs via node-pty; injects CLANKER_* into the shell; + - TerminalManager: real PTYs via node-pty; injects COMBOBULATE_* into the shell; a headless xterm resolves each PTY into a screen grid | WebSocket: /live (agents + world deltas + files) and /termview (screen grids) v - OpenRA mod (command-and-clanker/) - - ClankerBridge (world trait): connect on a background thread, apply deltas + OpenRA mod (command-and-combobulate/) + - CombobulateBridge (world trait): connect on a background thread, apply deltas on the game thread -> terminal buildings, folder walls, file buildings, agent units, fog - - ClankerTerminalWidget: a live, interactive terminal panel + - CombobulateTerminalWidget: a live, interactive terminal panel - Start menu: "Start Clanking" boots straight into the canvas map ``` ## How an agent reaches the map -Building a Terminal spawns a shell with `CLANKER_SESSION` (the terminal id), -`CLANKER_INGEST` (the ingest URL), and `CLANKER_TOKEN`. An agent launched there runs -a Command & Clanker adapter (see `integrations/`) that POSTs each tool call to +Building a Terminal spawns a shell with `COMBOBULATE_SESSION` (the terminal id), +`COMBOBULATE_INGEST` (the ingest URL), and `COMBOBULATE_TOKEN`. An agent launched there runs +a Command & Combobulate adapter (see `integrations/`) that POSTs each tool call to `/ingest`, authorized by the token and tagged with the session via -`X-Clanker-Session` (and the tool via `X-Clanker-Tool`). +`X-Combobulate-Session` (and the tool via `X-Combobulate-Tool`). ## Filesystem → map @@ -101,10 +101,10 @@ Two layers of placement caching keep the map calm: fills the gap nearest the origin instead of pushing everything outward. - Inside a folder, child order is `dirs.sort()` and the grid shape is a function of the child count, so adding a child only reshapes that subtree. -- The mod (`ClankerBridge`) lays files inside `fileArea` keyed by stable rows +- The mod (`CombobulateBridge`) lays files inside `fileArea` keyed by stable rows so an evicted file's neighbours do not slide. -Cache state is persisted to `.clanker-cache.json` (`server/persistence.ts`) +Cache state is persisted to `.combobulate-cache.json` (`server/persistence.ts`) so slots survive a backend restart. ### Wire-level summary @@ -145,7 +145,7 @@ TTL eviction + terminal sync). It holds no domain logic of its own. - **World builder** (`server/world-builder.ts`): a pure function of the live terminals and touched folders, producing terminal regions and a nested folder forest. `WorldService` (`server/world-service.ts`) wraps it with the - `PlacementCache` (`server/persistence.ts`, `.clanker-cache.json`) that keeps + `PlacementCache` (`server/persistence.ts`, `.combobulate-cache.json`) that keeps positions stable across restarts. - **Broadcaster** (`server/live.ts`): owns the connected `/live` clients and turns registry/world state into the `agents`, `world-delta`, and `files` wire @@ -158,7 +158,7 @@ TTL eviction + terminal sync). It holds no domain logic of its own. ### HTTP / WebSocket surface -- `POST /ingest` — agent events (token in `Authorization`, ids in `X-Clanker-*`). +- `POST /ingest` — agent events (token in `Authorization`, ids in `X-Combobulate-*`). - `GET /world` — one-shot world snapshot. - `POST /term/new`, `POST /term/kill` — terminal lifecycle. - `WS /term?id=` — raw PTY byte stream (`{i}` input, `{r:[c,r]}` resize). @@ -166,23 +166,23 @@ TTL eviction + terminal sync). It holds no domain logic of its own. - `POST /agent/freeze|unfreeze|interrupt|ask` — drive the agent's process. - `WS /live` — `agents`, `world-delta`, and `files` on each tick and on change. -## OpenRA mod (command-and-clanker/) +## OpenRA mod (command-and-combobulate/) Built on the OpenRA Mod SDK: `make` fetches the pinned engine (`mod.config` -`ENGINE_VERSION`) and builds `OpenRA.Mods.Clanker` against it. +`ENGINE_VERSION`) and builds `OpenRA.Mods.Combobulate` against it. -- **ClankerBridge** (`Traits/ClankerBridge.cs`, on the World actor): runs the +- **CombobulateBridge** (`Traits/CombobulateBridge.cs`, on the World actor): runs the `/live` WebSocket on a background thread that only enqueues messages; all World/Actor/resource changes happen on the game thread via `AddFrameEndTask`. It turns regions into terminal buildings and folder walls (laid out as a stable nested compounds), files into fog-hidden civilian buildings, and agents into units that drive to the folder they are working in. It also consumes `/termview` and forwards keystrokes back to the PTY. -- **ClankerTerminalWidget** (`Widgets/`): paints the screen grid in a monospace +- **CombobulateTerminalWidget** (`Widgets/`): paints the screen grid in a monospace font and routes keystrokes to the selected terminal — a live, interactive terminal inside the game. -- **Mod files** (`mods/clanker/`): rules, sequences, chrome, fluent, and the - `clanker-canvas` sandbox map; reuses OpenRA's Red Alert art. +- **Mod files** (`mods/combobulate/`): rules, sequences, chrome, fluent, and the + `combobulate-canvas` sandbox map; reuses OpenRA's Red Alert art. ## Wire shapes @@ -217,12 +217,12 @@ type AgentSnapshot = { ``` These TS wire types live in `shared/proc-types.ts` and `shared/types.ts` and are -hand-mirrored in the C# mod's `OpenRA.Mods.Clanker/Protocol/LiveMessage.cs`. +hand-mirrored in the C# mod's `OpenRA.Mods.Combobulate/Protocol/LiveMessage.cs`. `shared/wire-contract.test.ts` fails the test run if the two ever drift. ## Determinism Folder and terminal positions are deterministic: the backend's `PlacementCache` -assigns stable slots (persisted to `.clanker-cache.json`), and the mod lays +assigns stable slots (persisted to `.combobulate-cache.json`), and the mod lays folders out as a stable indented tree keyed by recycled rows, so the map does not reshuffle as folders come and go. diff --git a/integrations/claude/.claude-plugin/marketplace.json b/integrations/claude/.claude-plugin/marketplace.json index aed5c59..3fc98fe 100644 --- a/integrations/claude/.claude-plugin/marketplace.json +++ b/integrations/claude/.claude-plugin/marketplace.json @@ -1,11 +1,11 @@ { - "name": "clanker", - "owner": { "name": "Command & Clanker" }, + "name": "combobulate", + "owner": { "name": "Command & Combobulate" }, "plugins": [ { - "name": "clanker", - "source": "./clanker", - "description": "Stream Claude Code tool calls and subagents to the Command & Clanker map." + "name": "combobulate", + "source": "./combobulate", + "description": "Stream Claude Code tool calls and subagents to the Command & Combobulate map." } ] } diff --git a/integrations/claude/README.md b/integrations/claude/README.md index f678b0f..987f319 100644 --- a/integrations/claude/README.md +++ b/integrations/claude/README.md @@ -1,35 +1,35 @@ -# Command & Clanker adapter for Claude Code +# Command & Combobulate adapter for Claude Code This plugin streams every Claude Code tool call and subagent event to a -running Command & Clanker server (`POST /ingest`), so the agent's activity is rendered on +running Command & Combobulate server (`POST /ingest`), so the agent's activity is rendered on the map. It is the event source that replaces `/proc` scraping. ## How it ties to a terminal island -When you build a terminal inside Command & Clanker, the server injects three env vars into +When you build a terminal inside Command & Combobulate, the server injects three env vars into that shell: -- `CLANKER_SESSION` — the terminal island id (e.g. `t1`) -- `CLANKER_INGEST` — the ingest URL (default `http://127.0.0.1:3001/ingest`) -- `CLANKER_TOKEN` — a per-run token authorizing the endpoint +- `COMBOBULATE_SESSION` — the terminal island id (e.g. `t1`) +- `COMBOBULATE_INGEST` — the ingest URL (default `http://127.0.0.1:3001/ingest`) +- `COMBOBULATE_TOKEN` — a per-run token authorizing the endpoint -The hooks send `CLANKER_SESSION` and `CLANKER_TOKEN` as headers, so the server knows -which island the events belong to. Run Claude Code **inside an Command & Clanker terminal** +The hooks send `COMBOBULATE_SESSION` and `COMBOBULATE_TOKEN` as headers, so the server knows +which island the events belong to. Run Claude Code **inside an Command & Combobulate terminal** and its reads/writes/subagents animate on that terminal's island. ## Install From the repo, run `bun run setup` once: it merges these hooks (as an absolute command path) into `~/.claude/settings.json`, so any `claude` launched inside an -Command & Clanker terminal reports automatically. The hook is gated on `CLANKER_SESSION` and +Command & Combobulate terminal reports automatically. The hook is gated on `COMBOBULATE_SESSION` and runs with `curl --max-time 1`, so it is silent and non-blocking everywhere else. -No-install alternative: the Command & Clanker terminal injects `CLANKER_PATH` (this plugin's -directory), so you can run `claude --plugin-dir $CLANKER_PATH` instead. +No-install alternative: the Command & Combobulate terminal injects `COMBOBULATE_PATH` (this plugin's +directory), so you can run `claude --plugin-dir $COMBOBULATE_PATH` instead. To share it as a plugin, this directory's parent carries a `.claude-plugin/marketplace.json`; add it with -`/plugin marketplace add /integrations/claude` and install `clanker`. +`/plugin marketplace add /integrations/claude` and install `combobulate`. ## Events sent @@ -38,5 +38,5 @@ The server reads `tool_name` + `tool_input.file_path` to decide which folder a robot walks to (read vs write), and uses `agent_id` to distinguish subagents. > Note: the ingest URL is currently hardcoded to port 3001 in `hooks.json`. If -> you run the Command & Clanker server on another port, edit the `url` fields (the installer +> you run the Command & Combobulate server on another port, edit the `url` fields (the installer > will template this later). diff --git a/integrations/claude/clanker/.claude-plugin/plugin.json b/integrations/claude/clanker/.claude-plugin/plugin.json deleted file mode 100644 index 717957e..0000000 --- a/integrations/claude/clanker/.claude-plugin/plugin.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "clanker", - "description": "Stream Claude Code tool calls and subagent activity to the Command & Clanker map.", - "version": "0.1.0", - "author": { "name": "Command & Clanker" } -} diff --git a/integrations/claude/clanker/clanker-hook.sh b/integrations/claude/clanker/clanker-hook.sh deleted file mode 100755 index b9672e1..0000000 --- a/integrations/claude/clanker/clanker-hook.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# Command & Clanker hook: forward this tool/lifecycle event to the map. The tool -# name is the first argument, so each agent's adapter tags itself (claude, codex). -# Only acts inside a Command & Clanker terminal (CLANKER_SESSION is injected -# there), and is fast and silent so it never blocks the agent — safe to install -# globally. -[ -z "$CLANKER_SESSION" ] && exit 0 -[ -z "$CLANKER_INGEST" ] && exit 0 -tool="${1:-claude}" -curl -s --max-time 1 -X POST "$CLANKER_INGEST" \ - -H "content-type: application/json" \ - -H "authorization: Bearer ${CLANKER_TOKEN}" \ - -H "x-clanker-session: ${CLANKER_SESSION}" \ - -H "x-clanker-tool: ${tool}" \ - --data-binary @- >/dev/null 2>&1 || true -exit 0 diff --git a/integrations/claude/combobulate/.claude-plugin/plugin.json b/integrations/claude/combobulate/.claude-plugin/plugin.json new file mode 100644 index 0000000..2958e7d --- /dev/null +++ b/integrations/claude/combobulate/.claude-plugin/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "combobulate", + "description": "Stream Claude Code tool calls and subagent activity to the Command & Combobulate map.", + "version": "0.1.0", + "author": { "name": "Command & Combobulate" } +} diff --git a/integrations/claude/combobulate/combobulate-hook.sh b/integrations/claude/combobulate/combobulate-hook.sh new file mode 100755 index 0000000..8e8479c --- /dev/null +++ b/integrations/claude/combobulate/combobulate-hook.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Command & Combobulate hook: forward this tool/lifecycle event to the map. The tool +# name is the first argument, so each agent's adapter tags itself (claude, codex). +# Only acts inside a Command & Combobulate terminal (COMBOBULATE_SESSION is injected +# there), and is fast and silent so it never blocks the agent — safe to install +# globally. +[ -z "$COMBOBULATE_SESSION" ] && exit 0 +[ -z "$COMBOBULATE_INGEST" ] && exit 0 +tool="${1:-claude}" +curl -s --max-time 1 -X POST "$COMBOBULATE_INGEST" \ + -H "content-type: application/json" \ + -H "authorization: Bearer ${COMBOBULATE_TOKEN}" \ + -H "x-combobulate-session: ${COMBOBULATE_SESSION}" \ + -H "x-combobulate-tool: ${tool}" \ + --data-binary @- >/dev/null 2>&1 || true +exit 0 diff --git a/integrations/claude/clanker/hooks/hooks.json b/integrations/claude/combobulate/hooks/hooks.json similarity index 69% rename from integrations/claude/clanker/hooks/hooks.json rename to integrations/claude/combobulate/hooks/hooks.json index 40cf7ac..b1ee590 100644 --- a/integrations/claude/clanker/hooks/hooks.json +++ b/integrations/claude/combobulate/hooks/hooks.json @@ -1,19 +1,19 @@ { "hooks": { "SessionStart": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh claude" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh claude" }] } ], "SessionEnd": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh claude" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh claude" }] } ], "PostToolUse": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh claude" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh claude" }] } ], "SubagentStart": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh claude" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh claude" }] } ], "SubagentStop": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh claude" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh claude" }] } ] } } diff --git a/integrations/codex/.agents/plugins/marketplace.json b/integrations/codex/.agents/plugins/marketplace.json index cdb34f7..9536500 100644 --- a/integrations/codex/.agents/plugins/marketplace.json +++ b/integrations/codex/.agents/plugins/marketplace.json @@ -1,10 +1,10 @@ { - "name": "clanker", - "interface": { "displayName": "Command & Clanker" }, + "name": "combobulate", + "interface": { "displayName": "Command & Combobulate" }, "plugins": [ { - "name": "clanker", - "source": { "source": "local", "path": "./plugins/clanker" }, + "name": "combobulate", + "source": { "source": "local", "path": "./plugins/combobulate" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Coding" } diff --git a/integrations/codex/plugins/clanker/clanker-hook.sh b/integrations/codex/plugins/clanker/clanker-hook.sh deleted file mode 100755 index b9672e1..0000000 --- a/integrations/codex/plugins/clanker/clanker-hook.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# Command & Clanker hook: forward this tool/lifecycle event to the map. The tool -# name is the first argument, so each agent's adapter tags itself (claude, codex). -# Only acts inside a Command & Clanker terminal (CLANKER_SESSION is injected -# there), and is fast and silent so it never blocks the agent — safe to install -# globally. -[ -z "$CLANKER_SESSION" ] && exit 0 -[ -z "$CLANKER_INGEST" ] && exit 0 -tool="${1:-claude}" -curl -s --max-time 1 -X POST "$CLANKER_INGEST" \ - -H "content-type: application/json" \ - -H "authorization: Bearer ${CLANKER_TOKEN}" \ - -H "x-clanker-session: ${CLANKER_SESSION}" \ - -H "x-clanker-tool: ${tool}" \ - --data-binary @- >/dev/null 2>&1 || true -exit 0 diff --git a/integrations/codex/plugins/clanker/.codex-plugin/plugin.json b/integrations/codex/plugins/combobulate/.codex-plugin/plugin.json similarity index 53% rename from integrations/codex/plugins/clanker/.codex-plugin/plugin.json rename to integrations/codex/plugins/combobulate/.codex-plugin/plugin.json index d4076f6..5527727 100644 --- a/integrations/codex/plugins/clanker/.codex-plugin/plugin.json +++ b/integrations/codex/plugins/combobulate/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { - "name": "clanker", - "description": "Stream Codex tool calls and lifecycle events to the Command & Clanker map.", + "name": "combobulate", + "description": "Stream Codex tool calls and lifecycle events to the Command & Combobulate map.", "version": "0.1.0", "hooks": "./hooks/hooks.json", - "author": { "name": "Command & Clanker" } + "author": { "name": "Command & Combobulate" } } diff --git a/integrations/codex/plugins/combobulate/combobulate-hook.sh b/integrations/codex/plugins/combobulate/combobulate-hook.sh new file mode 100755 index 0000000..8e8479c --- /dev/null +++ b/integrations/codex/plugins/combobulate/combobulate-hook.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Command & Combobulate hook: forward this tool/lifecycle event to the map. The tool +# name is the first argument, so each agent's adapter tags itself (claude, codex). +# Only acts inside a Command & Combobulate terminal (COMBOBULATE_SESSION is injected +# there), and is fast and silent so it never blocks the agent — safe to install +# globally. +[ -z "$COMBOBULATE_SESSION" ] && exit 0 +[ -z "$COMBOBULATE_INGEST" ] && exit 0 +tool="${1:-claude}" +curl -s --max-time 1 -X POST "$COMBOBULATE_INGEST" \ + -H "content-type: application/json" \ + -H "authorization: Bearer ${COMBOBULATE_TOKEN}" \ + -H "x-combobulate-session: ${COMBOBULATE_SESSION}" \ + -H "x-combobulate-tool: ${tool}" \ + --data-binary @- >/dev/null 2>&1 || true +exit 0 diff --git a/integrations/codex/plugins/clanker/hooks/hooks.json b/integrations/codex/plugins/combobulate/hooks/hooks.json similarity index 70% rename from integrations/codex/plugins/clanker/hooks/hooks.json rename to integrations/codex/plugins/combobulate/hooks/hooks.json index 5d5799f..7aa8dfd 100644 --- a/integrations/codex/plugins/clanker/hooks/hooks.json +++ b/integrations/codex/plugins/combobulate/hooks/hooks.json @@ -1,13 +1,13 @@ { "hooks": { "SessionStart": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh codex" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh codex" }] } ], "SessionEnd": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh codex" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh codex" }] } ], "PostToolUse": [ - { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/clanker-hook.sh codex" }] } + { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/combobulate-hook.sh codex" }] } ] } } diff --git a/package.json b/package.json index 9483ff4..a11e19b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "command-and-clanker", + "name": "command-and-combobulate", "version": "0.0.4", "private": true, "type": "module", @@ -7,7 +7,7 @@ "dev": "node --experimental-strip-types --disable-warning=ExperimentalWarning --watch server/index.ts", "start": "node --experimental-strip-types --disable-warning=ExperimentalWarning server/index.ts", "setup": "node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/install.ts", - "game": "cd command-and-clanker && make && ./launch-game.sh", + "game": "cd command-and-combobulate && make && ./launch-game.sh", "typecheck": "tsc --noEmit", "test": "bun test" }, diff --git a/scripts/install.ts b/scripts/install.ts index 8461ba3..7f7963a 100644 --- a/scripts/install.ts +++ b/scripts/install.ts @@ -1,6 +1,6 @@ -// `bun run setup` — wire the Command & Clanker adapters into the agent CLIs so +// `bun run setup` — wire the Command & Combobulate adapters into the agent CLIs so // you do not have to pass plugin paths by hand. Every adapter only does anything -// inside a Command & Clanker terminal (where CLANKER_SESSION is injected), so this +// inside a Command & Combobulate terminal (where COMBOBULATE_SESSION is injected), so this // is safe to run once globally. Idempotent. // // claude — a hook in ~/.claude/settings.json. @@ -12,9 +12,9 @@ import { dirname, join, resolve } from "node:path"; import { spawnSync } from "node:child_process"; const repo = resolve(import.meta.dirname, ".."); -const claudeHook = resolve(repo, "integrations/claude/clanker/clanker-hook.sh"); +const claudeHook = resolve(repo, "integrations/claude/combobulate/combobulate-hook.sh"); const codexMarketplace = resolve(repo, "integrations/codex"); -const codexHook = resolve(repo, "integrations/codex/plugins/clanker/clanker-hook.sh"); +const codexHook = resolve(repo, "integrations/codex/plugins/combobulate/combobulate-hook.sh"); const home = homedir(); const CLAUDE_EVENTS = [ @@ -26,9 +26,9 @@ const CLAUDE_EVENTS = [ ]; // Hook commands left by this or a previous install. Re-running setup strips -// these before re-adding, so entries never stack. "aiso-hook.sh" is the -// pre-rebrand name and is cleaned up here too. -const STALE_HOOK_NAMES = ["clanker-hook.sh", "aiso-hook.sh"]; +// these before re-adding, so entries never stack. "clanker-hook.sh" and +// "aiso-hook.sh" are earlier pre-rebrand names and are cleaned up here too. +const STALE_HOOK_NAMES = ["combobulate-hook.sh", "clanker-hook.sh", "aiso-hook.sh"]; function has(cmd: string): boolean { return spawnSync("sh", ["-c", `command -v ${cmd}`], { stdio: "ignore" }).status === 0; @@ -68,20 +68,20 @@ async function installCodex(): Promise { stdio: "ignore", timeout: 30000, }); - spawnSync("codex", ["plugin", "add", "clanker@clanker"], { + spawnSync("codex", ["plugin", "add", "combobulate@combobulate"], { stdio: "ignore", timeout: 30000, }); - return "added clanker@clanker (trust its hooks in Codex on first use)"; + return "added combobulate@combobulate (trust its hooks in Codex on first use)"; } const claude = await installClaude(); const codex = await installCodex(); -console.log("Command & Clanker adapters installed:"); +console.log("Command & Combobulate adapters installed:"); console.log(` Claude hooks -> ${claude}`); console.log(` Codex plugin -> ${codex}`); console.log( - "They only report inside Command & Clanker terminals (CLANKER_SESSION is", + "They only report inside Command & Combobulate terminals (COMBOBULATE_SESSION is", ); console.log("injected there), so they stay quiet everywhere else. Run an agent and watch the map."); diff --git a/server/files.test.ts b/server/files.test.ts index bbaf0f1..1e3f4af 100644 --- a/server/files.test.ts +++ b/server/files.test.ts @@ -83,7 +83,7 @@ describe("FileRegistry", () => { describe("FileRegistry size", () => { let dir: string; beforeAll(() => { - dir = mkdtempSync(join(tmpdir(), "clanker-files-")); + dir = mkdtempSync(join(tmpdir(), "combobulate-files-")); }); afterAll(() => { rmSync(dir, { recursive: true, force: true }); diff --git a/server/http.test.ts b/server/http.test.ts index a51211e..f90b5f1 100644 --- a/server/http.test.ts +++ b/server/http.test.ts @@ -50,7 +50,7 @@ function harness(terminals?: Partial): HttpDeps { { refs: () => [] } as unknown as TerminalManager, workDirs, emptyCache(), - "/tmp/clanker-http-test-cache.json", + "/tmp/combobulate-http-test-cache.json", ); return { ingestToken: TOKEN, @@ -90,8 +90,8 @@ describe("http /ingest auth", () => { fakeReq("POST", "/ingest", { headers: { authorization: `Bearer ${TOKEN}`, - "x-clanker-session": "t1", - "x-clanker-tool": "claude", + "x-combobulate-session": "t1", + "x-combobulate-tool": "claude", }, body: JSON.stringify({ hook_event_name: "SessionStart" }), }), diff --git a/server/http.ts b/server/http.ts index 4780aa1..8fb3d7b 100644 --- a/server/http.ts +++ b/server/http.ts @@ -57,22 +57,22 @@ export function createHttpHandler(deps: HttpDeps) { if (req.headers["authorization"] !== `Bearer ${ingestToken}`) { return sendJson(res, 401, { ok: false }); } - const session = String(req.headers["x-clanker-session"] ?? ""); - const tool = String(req.headers["x-clanker-tool"] ?? "claude"); + const session = String(req.headers["x-combobulate-session"] ?? ""); + const tool = String(req.headers["x-combobulate-tool"] ?? "claude"); let body: ClaudeHook = {}; try { body = parseHook(await readBody(req)) ?? {}; } catch { /* ignore malformed */ } - if (process.env.CLANKER_DEBUG_INGEST) { + if (process.env.COMBOBULATE_DEBUG_INGEST) { console.log( `[ingest] tool=${tool} session=${session} body=${JSON.stringify(body)}`, ); } if (session) { sessions.handle(session, tool, body); - if (process.env.CLANKER_DEBUG_INGEST) { + if (process.env.COMBOBULATE_DEBUG_INGEST) { const a = agents.get(session); const sub = body.agent_id ? agents.get(subId(session, body.agent_id)) : null; const target = sub ?? a; diff --git a/server/index.ts b/server/index.ts index 2ed8cf3..360a9ad 100644 --- a/server/index.ts +++ b/server/index.ts @@ -17,13 +17,13 @@ const PORT = Number(process.env.TTY_API_PORT ?? 3001); const TICK_MS = 1000; const ACTIVITY_TTL_MS = 6000; const CACHE_PATH = - process.env.CLANKER_CACHE ?? join(process.cwd(), ".clanker-cache.json"); -const INGEST_TOKEN = process.env.CLANKER_TOKEN ?? randomUUID(); + process.env.COMBOBULATE_CACHE ?? join(process.cwd(), ".combobulate-cache.json"); +const INGEST_TOKEN = process.env.COMBOBULATE_TOKEN ?? randomUUID(); -// Absolute path to the Claude plugin dir, injected as CLANKER_PATH and used as -// `claude --plugin-dir $CLANKER_PATH`. +// Absolute path to the Claude plugin dir, injected as COMBOBULATE_PATH and used as +// `claude --plugin-dir $COMBOBULATE_PATH`. const INTEGRATIONS = resolve(import.meta.dirname, "..", "integrations"); -const PLUGIN_DIR = resolve(INTEGRATIONS, "claude", "clanker"); +const PLUGIN_DIR = resolve(INTEGRATIONS, "claude", "combobulate"); const placements = await loadCache(CACHE_PATH); const knownTerminals = new Set(); diff --git a/server/ingest.test.ts b/server/ingest.test.ts index bd8324f..dad60b0 100644 --- a/server/ingest.test.ts +++ b/server/ingest.test.ts @@ -20,7 +20,7 @@ function harness() { return { agents, transcripts, ingest, dirty: () => dirty }; } -const MAIN = "/tmp/clanker-test-main.jsonl"; +const MAIN = "/tmp/combobulate-test-main.jsonl"; describe("Ingest session lifecycle", () => { test("SessionStart creates a main agent", () => { diff --git a/server/live.test.ts b/server/live.test.ts index 6d6bf18..7d2cfe3 100644 --- a/server/live.test.ts +++ b/server/live.test.ts @@ -26,7 +26,7 @@ function harness() { { refs: () => [] } as unknown as TerminalManager, new WorkDirTracker(), emptyCache(), - "/tmp/clanker-live-test-cache.json", + "/tmp/combobulate-live-test-cache.json", ); return { agents, files, broadcaster: new Broadcaster(agents, files, worldService) }; } diff --git a/server/persistence.test.ts b/server/persistence.test.ts index 9d1856c..082e163 100644 --- a/server/persistence.test.ts +++ b/server/persistence.test.ts @@ -7,14 +7,14 @@ import { buildWorld, emptyCache, type TerminalInfo } from "./world-builder.ts"; const term = (id: string): TerminalInfo => ({ id, label: id }); -const path = join(tmpdir(), `clanker-cache-${process.pid}-${Date.now()}.json`); +const path = join(tmpdir(), `combobulate-cache-${process.pid}-${Date.now()}.json`); afterEach(async () => { await rm(path, { force: true }); }); test("returns an empty cache when the file is missing", async () => { - const cache = await loadCache(join(tmpdir(), "clanker-does-not-exist.json")); + const cache = await loadCache(join(tmpdir(), "combobulate-does-not-exist.json")); expect(cache.region.size).toBe(0); expect(cache.building.size).toBe(0); expect(cache.freeRegionSlots).toEqual([]); diff --git a/server/terminals.ts b/server/terminals.ts index c67da9a..7f9ec7e 100644 --- a/server/terminals.ts +++ b/server/terminals.ts @@ -173,10 +173,10 @@ export class TerminalManager { // The agent's adapter reads these to tag its events with this island and // reach the ingest endpoint. const env = { - CLANKER_SESSION: id, - CLANKER_INGEST: this.ingest.url, - CLANKER_TOKEN: this.ingest.token, - CLANKER_PATH: this.ingest.pluginDir, + COMBOBULATE_SESSION: id, + COMBOBULATE_INGEST: this.ingest.url, + COMBOBULATE_TOKEN: this.ingest.token, + COMBOBULATE_PATH: this.ingest.pluginDir, }; this.terminals.set( id, diff --git a/server/transcript-tailer.test.ts b/server/transcript-tailer.test.ts index 9ee669a..5f3338c 100644 --- a/server/transcript-tailer.test.ts +++ b/server/transcript-tailer.test.ts @@ -8,7 +8,7 @@ let dir: string; let path: string; beforeEach(() => { - dir = mkdtempSync(join(tmpdir(), "clanker-tail-")); + dir = mkdtempSync(join(tmpdir(), "combobulate-tail-")); path = join(dir, "session.jsonl"); }); diff --git a/server/world-service.test.ts b/server/world-service.test.ts index ab2c992..f93c502 100644 --- a/server/world-service.test.ts +++ b/server/world-service.test.ts @@ -17,7 +17,7 @@ function fakeTerminals(refs: { id: string; pid: number }[]): TerminalManager { describe("WorldService", () => { let dir: string; beforeAll(() => { - dir = mkdtempSync(join(tmpdir(), "clanker-world-")); + dir = mkdtempSync(join(tmpdir(), "combobulate-world-")); }); afterAll(() => { rmSync(dir, { recursive: true, force: true }); diff --git a/shared/wire-contract.test.ts b/shared/wire-contract.test.ts index d0c2a97..89925be 100644 --- a/shared/wire-contract.test.ts +++ b/shared/wire-contract.test.ts @@ -10,7 +10,7 @@ import type { AgentSnapshot, FileActivity, FileEntry, FolderFiles } from "./proc // C# [JsonPropertyName] is added (and vice versa). const LIVE_MESSAGE_CS = resolve( import.meta.dir, - "../command-and-clanker/OpenRA.Mods.Clanker/Protocol/LiveMessage.cs", + "../command-and-combobulate/OpenRA.Mods.Combobulate/Protocol/LiveMessage.cs", ); // Parse the C# model into { className: [jsonPropertyName, ...] } by reading the