Skip to content

Releases: NeoXider/CoreAI

v6.13.1 — stock Lua-CSharp 0.5.6

Choose a tag to compare

@NeoXider NeoXider released this 31 Jul 07:57

The bundled Lua VM is now stock Lua-CSharp v0.5.6 instead of a locally patched 0.5.5 build.

  • WebGL coroutines work. 0.5.5 posted a suspended coroutine's continuation to the ambient SynchronizationContext — on Unity's main thread that is the very thread parked in GetAwaiter().GetResult(), so a single-threaded WASM player froze on the first coroutine.yield. Fixed upstream as nuskey8/Lua-CSharp#329, for the deadlock reported as #327.
  • The local VM patch is retired. #t returning nil under the sandbox's instruction hook — patched into our own Lua.dll since July — landed upstream as #331, so the shipped binary is unmodified upstream again.
  • Lua runs ~25% faster (#330): a tight loop 30 ms → 22 ms raw, 165 ms → 127 ms under the sandbox guard.

Drop-in swap: the assembly's public API is identical member-for-member. EditMode: 2538 tests, 2529 passed, 0 failed, 9 skipped.

CoreAI 6.12.0

Choose a tag to compare

@NeoXider NeoXider released this 30 Jul 10:17

Fixes a bug where spawning a Part could wipe every part in the world and then fail with an error blaming the script.

Fixed

Instance.new after the world host died now says so. When the RbxWorldHost that owns a world is destroyed — a scene load, a domain reload during play, or leaving play mode — its teardown destroys the whole DataModel and every part in it. The mod stack survives, because the Lua bindings capture the InstanceRegistry once at install time, so scripts kept writing into a registry whose scene was gone. The next spawn failed at the parent assignment with PARENT_LOCKED about Workspace, which reads as a mistake in the mod's own code. Scripted creation now fails immediately with a new WORLD_DETACHED code that names the lost host and says to reload the mods. Host-level creation (snapshot restore, service bootstrap) is unaffected, so a world can still be rebuilt.

A refused MCP request reached the client as a dropped connection. The server wrote 413/415/401 and closed while the client was still sending; the OS answered the unread body with a reset that discarded the response. Refusals now drain the pending body first, up to 64 KB.

The MCP server advertised the wrong version. serverInfo.version was a hand-maintained constant the release tooling never touched, answering 6.9.0 while the packages shipped 6.11.1. tools/bump_version.py now rewrites it with every manifest and --check fails when they disagree.

Added

RbxErrorCode.WorldDetached, InstanceRegistry.IsDetached / MarkDetached(), RbxError.WorldDetached() — additive public API, hence a minor release.

Changed

// WHY: comments pruned across all six packages (1065 → 958) and ~55 tightened, so the ones recording a real constraint stand out. Comments only — no code changed. Also restored 24 XML doc blocks corrupted by an earlier pass and repaired 13 double-encoded em-dashes.

Verification: EditMode 2530 tests — 2521 passed, 0 failed, 9 skipped.

v6.11.1 - the Rbx API mods actually use, finally documented

Choose a tag to compare

@NeoXider NeoXider released this 29 Jul 19:34

Stable documentation release. It also carries 6.11.0, which was committed but never tagged or released.

The problem this fixes

The documentation taught the classic coreai_world_spawn / _change / _set_color / _destroy
build API as the way for a Lua mod to create world objects — but the default composition
(CoreAiModsInstaller) sets RegisterWorldEditBuildBindings = false, so every one of those calls is
a stub that raises LuaApiWithheldException. Meanwhile the API a mod actually uses — the
Roblox-style Instance.new surface — was documented nowhere at all.

Added

  • CoreAI/Docs/RBX_API.md — the missing reference: Instance.new and the supported classes,
    the datatype and service globals actually registered by LuaCsRbxApiBindings, the Part property
    set, a complete working mod, the four bundled sample mods (and the fact that the three playable
    ones ship active: false, enabled from the Hub → Mods tab), and the verified IL2CPP/WebGL
    stripping story. Linked from both documentation indexes.
  • KNOWN_ISSUES.md — four real defects that were unrecorded:
    • the FullAccess demo's Start Tetris and the LuaMods demo's wave_started both throw,
      because their Lua is still written against the withheld build API (the bundled sample_tetris3d
      mod is the working equivalent);
    • LLMUnity throws ArgumentException: Unknown platform Unix on WebGL startup;
    • the legacy log-settings migration widens to GameLogFeature.AllBuiltIn, which excludes
      CustomA — so an upgraded project silently stops showing Lua mod errors;
    • Windows IL2CPP needs the MSVC C++ workload plus Windows SDK 10.0.19041+.
  • WEBGL_BUILD_TROUBLESHOOTING.mdCS0103: WebGLInput does not exist: WebGLModule.dll is
    added to the reference set only when the active build target is already WebGL, so a
    #if UNITY_WEBGL guard does not save you — switch the platform first. Plus the
    "scripts are compiling" race right after a platform switch, the shipped WebGL settings
    (IL2CPP, Medium stripping, OptimizeSize, Brotli with JS fallback), and what link.xml was
    verified to preserve.

Fixed

  • LUA_GAME_API.md and FIRST_MOD.md now lead with the Rbx API and scope the classic build surface
    to hosts that deliberately opt in. The read-only queries (coreai_world_exists / _pos / _find
    / _list_prefabs / _raycast) are unaffected and are marked as such. Same correction in the
    LiveMechanics, LiveMechanicsMods, LuaMods and MCP READMEs.
  • RbxApi/Instances/README.md still described signals as NOT_IMPLEMENTED stubs awaiting a
    scheduler and the Unity binder as unwritten — both shipped long ago.
  • DOCS_INDEX.md omitted five docs that exist on disk.
  • INSTALL.md claimed Lua runs under IL2CPP/WebGL "without extra stripping protection" while the
    package ships a link.xml doing exactly that.
  • SHIPPING_PLAYER_MACHINES.md now states that Windows Standalone currently ships Mono2x.

Also in this release (6.11.0, previously untagged)

  • CoreAiChatPanel.TurnStreamingBubbles — the prose bubbles of the current turn, in the order
    they were opened. A turn splits into several bubbles when tool rounds run between prose, but
    OnResponseReceived handed the host the whole turn concatenated, so hosts that post-process
    bubbles had to rediscover them from the visual tree by CSS class and text matching. One shipping
    host re-rendered the whole response into the last bubble, duplicating prose and leaving the sealed
    bubble unrendered.

Verified

All six packages move in lockstep at 6.11.1. No runtime code changed in 6.11.1.

The WebGL/IL2CPP claims in these docs come from a real player build at Medium managed stripping:
the VContainer container builds, RbxWorldHost binds instances, bundled mods seed, the Lua VM runs a
16-check self-test with zero failures, and a mod-driven Instance.new spawns visible parts.

v6.10.0 — MCP security, six headless demo scenes, and a long tail of silent failures

Choose a tag to compare

@NeoXider NeoXider released this 29 Jul 13:32

Acts on fresh audits of all five packages.

⚠️ Security

The in-game MCP server accepted cross-origin requests. Binding to 127.0.0.1 stops network access but not the user's own browser: with Content-Type: text/plain a POST is a "simple" CORS request and skips preflight, so any open web page could call tools/call execute_lua or manage_mods — and DNS rebinding makes the request same-origin, exposing replies including screenshot.

Requests are now screened before routing (IsLocalHostOrigin → JSON Content-Type) and authenticated with a bearer token, generated per run or pinned via COREAI_MCP_TOKEN. The server remains off by default and is in no shipped scene.

Migration: existing clients must send Authorization: Bearer <token>. The token is printed to the game console with a ready-to-paste command; set COREAI_MCP_TOKEN once for a stable config.

Fixed

  • Six published demo scenes ran mods headlessInstance.new produced nothing in them. CoreAiHubDemo, LiveMechanicsDemo, LiveMechanicsModsChatDemo, WaveAutoBattlerModsDemo, MiniRpgModsDemo and ModdableUnitsDemo now each carry a wired RbxWorldHost.
  • Editing a mod in the Hub froze the game.
  • LLMManager.LoadFromDisk() wiped the LLMUnity model registry in the Editor — a "rescan" that erased the user's registered models, permanently once anything saved afterwards.
  • A ChainReset past the first line no longer verifies an audit log as intact. Truncating the tail and appending a forged restart used to report Ok.

Failures that were silent by construction

  • A library timeout surfaced as "cancelled", so it read as if the user pressed Stop and the timeout branch never ran.
  • An empty streaming response counted as success while vanishing from history and traces.
  • MutateAsync destroyed a role's memory when the load failed rather than being absent.
  • game_config update reported success when the store rejected the write.
  • WebGL: Task.Delay in the endpoint drain loop never resumed and wedged activation forever; seven unguarded SwitchToThreadPool calls hung tool turns; an unclamped transcript entry could crash the player.

Added

GameLogFilter — a real runtime logging API over a runtime copy of the authored ScriptableObject, so filters change in a player without mutating the asset. GameLogFeature.All now actually includes every category (it silently omitted Metrics), the no-asset default no longer ignores categories or mutes everything below Warning, and the static fallback used by ~15 files is finally under the same filter. First tests that prove filtering drops messages, rather than only testing the predicate.

Verification

EditMode: 2539 tests, 0 failed. The demo-scene smoke test passes after the scene fix. Remaining PlayMode failures are a local LM Studio that cannot load its model, plus one pre-existing TargetCube assertion that reproduces identically on a clean HEAD.

v6.8.3 — mod-spawned parts were invisible in every build

Choose a tag to compare

@NeoXider NeoXider released this 29 Jul 07:29

The real fix for "mods spawn nothing in a build" — and a correction: 6.8.2 blamed the wrong cause.

Fixed

Parts spawned by mods were invisible in every player build. They were always there — active, correctly sized, collidable. They just drew nothing.

URP declares UniversalRenderPipelineAsset.defaultMaterial under #if UNITY_EDITOR, so in a player it returns null and GameObject.CreatePrimitive substitutes the built-in Default-Material (shader Standard). That material is not null — so a null check never caught it — and URP cannot render a built-in shader.

InstanceGameObjectBinder now builds its default material from the active pipeline's own shader whenever a Scriptable Render Pipeline is present, instead of trusting the primitive's material. Cylinders get it assigned explicitly, Universal Render Pipeline/Lit is in Always Included Shaders, and an unresolvable shader is now a loud error.

Correction to 6.8.2

That release attributed this to IL2CPP managed stripping and added link.xml entries. Measured on the live editor, Standalone builds with Mono2x and managed stripping Disabled — no managed stripping happens there at all, and the symptom reproduced identically on Mono and IL2CPP. Stripping could not have been the cause. The link.xml entries are kept, because they are correct and necessary for WebGL (which strips at Medium), but they fixed nothing here.

Added — the failure is no longer silent

A part that is created but never drawn is indistinguishable from one that was never created, and a player has no inspector to tell them apart. That is precisely why this bug survived a long debugging session.

  • The binder reports the first materialized part with its renderer and resolved shader — once, not per part, so a mod spawning in bulk cannot flood the console.
  • InstanceRegistry gained an engine-free Diagnostics hook that reports an instance entering a tree the registry does not own. That path was previously an early return: no log, no exception, no object.

Verification

Confirmed in an actual Windows player: parts render, and the shader resolves to Universal Render Pipeline/Lit (it read Standard before the fix). EditMode: 2427 tests, 0 failed.

v6.8.0 — audit fixes, fail-closed key guards, two reverts

Choose a tag to compare

@NeoXider NeoXider released this 24 Jul 21:12

Acts on the 6.7.0 audits of the core, Unity and Hub packages.

⚠️ Breaking / migration

  • A provider key inside a Resources/ settings asset now FAILS the build on every platform, instead of logging "Building anyway". Anything under Resources/ is packed into the player and the key is recoverable from the shipped build. Clear apiKey/secondaryApiKey on committed Resources assets and supply the key at runtime. WebGL key leaks in ClientOwnedApi/ClientLimited/ServerManagedApi fail the build too.
  • ICoreAiComponentCommandExecutor.LastListedComponents is removed, replaced by TryExecute(cmd, out List<string> listedComponents) — tool calls run in parallel, so a listing on shared executor state could be overwritten before its consumer read it.
  • Default assets are no longer auto-created on editor load. Use CoreAI/Setup/Create Default Assets or CoreAI/Settings.

Fixed

  • Queue-pump deadlock in QueuedAiOrchestrator: work started synchronously under _lock, and its first statement disposed a cancellation registration that blocks on a callback waiting for that same lock.
  • OperationCanceledException was retried as a provider fault in three places; caller cancellation now propagates immediately.
  • SetTools silently did nothing on chains fronted by ClientLimitedLlmClientDecorator or LoggingLlmClientDecorator. A reflection sweep test now requires every decorator to declare every virtual interface member.
  • Half-open probe slot leak in the circuit breaker; unbounded static lock tables keyed by model-controlled ids; Packages/manifest.json corruption; non-atomic endpoint-registry saves; WebGL SwitchToThreadPool hangs; an editor capture leak and a main-thread marshaler hang.
  • Hub: sub-tab lifecycle on revisit, remove-confirm state lost on list rebuild, and settings Apply silently downgrading ClientLimited/ServerManagedApi.
  • The PlayMode suite could not run past test 32. A guard used Application.CanStreamedLevelBeLoaded, which reports false in the Editor even for a registered and enabled scene; the resulting Assert.Ignore on the first MoveNext() of a [UnityTest] wedged the runner and blocked the remaining 139 tests.

Reverted — both traded a guarantee for a small measured win

  • Clock sampling in the Lua execution guard, shipped in 6.7.0 and documented there as "free and risk-free". It was not: the count hook does not fire during a host call, so a handler of a few hundred instructions that are mostly bindings can blow a per-frame budget while never reaching the sampling threshold — defeating the timeout in the case it matters most. Reverting costs ~6%; dev-docs/LUA_PERF_AUDIT_v6.6_2026-07.md records how to recover it safely.
  • RbxScriptSignal.Fire1/Fire2, reverted before shipping: the reused argument buffer is incompatible with the MVP2 scheduler's deferred dispatch, where the argument array outlives the Fire call, and it removed one array out of N+1.

Verification

EditMode: 2427 tests, 0 failed. PlayMode: 171 run; the 2 remaining failures reproduce identically on a clean HEAD (a missing local GGUF model, and a demo-scene assertion) and are tracked separately. Windows player builds clean at 615.89 MB.

CoreAI v6.7.0

Choose a tag to compare

@NeoXider NeoXider released this 24 Jul 18:14

Prompt-delivery fix, a measured Lua guard optimization, and a full read-only audit of the Hub, core and Unity packages.

Fixed

  • Built-in agent prompts never reached a Unity host. AgentPromptsInstaller chains the Resources/AgentPrompts/System provider ahead of the built-in one, so a prompt shipped there permanently shadows its C# const — and the package shipped copies of seven built-in prompts. The shipped Programmer.txt had already drifted: it was missing the "answer plain questions directly — do NOT call read_skill or any tool for those" rule, the report()/logic_* globals list, and the Forbidden: io, os, require, load, loadfile, dofile, debug line. Every Unity host was therefore running an older Programmer prompt than the code said.

    The eight shadowing/dead assets are deleted (PlayerChat.txt was dead outright — the role id became PlainChat), leaving DeveloperSampleAgent.txt, which has no const. Resources/AgentPrompts/System is now purely the consumer's override slot, as its own doc comment says. A new test, NoBuiltInRolePromptIsShadowedByAShippedResourceCopy, fails if such a copy is reintroduced.

Changed

  • Lua execution guard: the wall clock is now sampled every 64th hook fire instead of every fire. Measured: Stopwatch.GetTimestamp() ~44 ns vs ~14 ns for the heap read, i.e. ~76% of the work inside a hook that fires every 4 VM instructions. The step budget is still charged on every fire, so a runaway is cut exactly as before. Guarded-execution overhead: 3.67× → 3.21×.

Docs

  • dev-docs/LUA_PERF_AUDIT_v6.6_2026-07.md — two findings worth reading: the published Luau comparison was measured without the execution guard and understates the real gap by ~3.7×; and the guard's cost is dominated by the number of hook fires (~600 ns each — the VM's async hook dispatch), not the work inside the hook. Raising the batch to 64 measures 1.21× overhead (a 2.65× speedup) but was deliberately not shipped: the small batch is load-bearing for the allocation-bomb backstop. The doc specifies the adaptive-batch design that would capture the win safely.
  • dev-docs/CODE_AUDIT_v6.6_2026-07.md — audit backlog for CoreAIHub, CoreAI and CoreAiUnity.

Full EditMode suite: 2386 passed, 0 failed, 9 skipped (intentional).

CoreAI v6.6.0

Choose a tag to compare

@NeoXider NeoXider released this 24 Jul 17:49

RobloxRbx identifier cleanup across the C# codebase, plus two test/doc fixes carried over from 6.5.0.

Changed

  • "Roblox" removed from C# identifiers (naming convention: Rbx, not Roblox). Renamed every C# type, interface, member, test class and test namespace that carried Roblox in its name to the Rbx form — RobloxSpaceRbxSpace, RobloxWorldHostRbxWorldHost, RobloxCameraFollowerRbxCameraFollower, IRobloxCameraRigIRbxCameraRig, RobloxApiStubExceptionRbxApiStubException, LuaCsRoblox*LuaCsRbx*, the RobloxApi member/namespace leaf→RbxApi, and all Roblox*EditModeTests/RobloxApi4BLiveCheck*Rbx*. 25 source files renamed (.cs+.meta, GUIDs preserved); the three affected demo scenes updated.

    The word "Roblox" is intentionally kept where it names the actual platform — comments, XML docs, the agent skill text, loud-stub/log messages, and test-method descriptions that assert Roblox parity — so the Roblox-compatibility story stays legible. Pure rename: no behaviour change.

Fixed

  • Two tests reconciled with 6.5.0 behaviour changes. The LuaCs_ModsCall_*_CannotDisarmHandlerGuard guard tests now pin a tight per-handler step/time budget instead of relying on the (now Roblox-parity) default, so they still prove the outer guard survives a nested mods_call. The bundled-seeder test and the BundledModSeeder class doc were updated to match the shipped "a strictly-newer bundled version is canonical and ships, superseding a local edit (prior source kept in the store's revision history)" policy.

Full EditMode suite green (2395/2395). Windows player and Android APK rebuilt.

Previous release (v6.5.0) shipped ClickDetector 3D click-picking, the sample_clicker block-clicker sample, Roblox-parity execution budgets (~10 s), and reliable mod versioning/delivery.

CoreAI v6.3.0

Choose a tag to compare

@NeoXider NeoXider released this 24 Jul 07:14

CoreAI v6.3.0 — MVP1 "Roblox API" completion. A mod can now build, query, clone and destroy an instance tree, read keyboard/mouse input, drive the camera, and pick a Part shape — all through the Roblox‑1:1 Lua surface. Plus a reasoning/think‑block streaming fix and a per‑frame allocation pass. All six com.neoxider.* packages advance to 6.3.0 in lockstep.

Added

  • UserInputService (Roblox 1:1)game:GetService("UserInputService"): InputBegan/InputEnded/InputChanged firing (InputObject, gameProcessedEvent) with real RBXScriptConnection, the poll surface (IsKeyDown, GetKeysPressed, GetMouseLocation, MouseBehavior), and Enum.KeyCode/UserInputType/UserInputState/MouseBehavior at exact Roblox names+values. Backed by a swappable IInputSource seam; pumped once per frame before mod dispatch.
  • workspace.CurrentCamera — a real Camera instance with CFrame/CameraType/CameraSubject over a swappable camera‑rig seam, plus camera_set_cframe/camera_follow globals. Reads ungated, writes WorldEdit‑gated.
  • Part.Shape (Enum.PartType) — Ball, Cylinder (axis‑corrected mesh child), Wedge (custom 1‑unit ramp mesh + convex collider); CornerWedge accepted (draws as Block for now).
  • Rbx skill (read_skill("Rbx API")) now documents input, camera and Shape with a keyboard‑driven mini‑game example.

Fixed

  • Reasoning / think‑block streaming surfaces reasoning_content/reasoning deltas and promotes reasoning to visible content when a model emits no plain content, so reasoning‑only models no longer return empty responses (flows to the WebGL fetch transport too).
  • Token budget estimated when the server returns none (incl. reasoning chars), so the budget page populates instead of reading zero.
  • Instance:Clone() deep‑copies BasePart state (Size/CFrame/Color/Anchored/Shape) onto the clone.
  • Recursive FindFirstChild/FindFirstChildWhichIsA now search depth‑first (Roblox parity).
  • Services and the canonical Camera are locked against a mod removing them — Destroy() errors, Clone() returns nil, reparenting errors, and ClearAllChildren() skips them.
  • Part appearance/collision target the part's own visual (identified by an owned reference, not the child name "Shape").
  • Full‑tier withheld stubs register even when Full is granted but unwired, so unity_* raises the actionable error.
  • FullAccessDemo invisible spawns fixed (RobloxWorldHost wired into the mods scope); Hub AI Settings placeholder/foldout fixes.

Performance

  • Binder: per‑aspect property re‑apply (a CFrame/Size write skips full re‑materialization); cached Renderer/Collider/Rigidbody refs + MaterialPropertyBlock; cached primitive meshes/material.
  • RbxScriptSignal.Fire reuses the fire‑snapshot buffer; input signals pass a cached boxed false.
  • Input event objects gated on HasConnections — a mouse‑move frame with no listener allocates no InputObject.
  • RbxCFrame multiply/equality read struct fields directly (no per‑op float[12]).

Full changelog: Assets/CoreAI/CHANGELOG.md

CoreAI v6.2.1

Choose a tag to compare

@NeoXider NeoXider released this 23 Jul 11:28

CoreAI v6.2.1 — patch over v6.2.0. Restores the CI package-lockstep gate (internal com.neoxider.* dependency pins were left at 6.0.0 while packages were 6.2.0), adds a one-command lockstep version-bump script, and lands a root-README accuracy audit.

Fixed

  • Package lockstep restored: the 6.0→6.2 version bumps advanced each package's version but left the
    internal com.neoxider.* dependency pins at 6.0.0, so the CI "Package graph (lockstep + deps)" gate
    failed with 11 mismatches. All six packages now pin the shared version. (supersedes the v6.2.0 tag,
    whose published package.json files still carried the stale 6.0.0 pins)

Added

  • tools/bump_version.py — one command bumps every Assets/*/package.json version and every
    internal com.neoxider.* dependency pin to a target version in lockstep, then self-verifies with the
    same rule the CI gate enforces (python tools/bump_version.py 6.2.1, or --check to verify only).

Docs

  • Root README audit: corrected the package count (six, including the new CoreAI MCP Server
    package), fixed a wrong tool class name (WorldCommandToolWorldLlmTool / world_command), and
    reflected the 6.2.0 features (mod runtime self-heal, vision Detect self-probe, Hub sub-tabs).

Full changelog: Assets/CoreAI/CHANGELOG.md