Releases: NeoXider/CoreAI
Release list
v6.13.1 — stock Lua-CSharp 0.5.6
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 inGetAwaiter().GetResult(), so a single-threaded WASM player froze on the firstcoroutine.yield. Fixed upstream as nuskey8/Lua-CSharp#329, for the deadlock reported as #327. - The local VM patch is retired.
#treturning nil under the sandbox's instruction hook — patched into our ownLua.dllsince 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
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
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.newand the supported classes,
the datatype and service globals actually registered byLuaCsRbxApiBindings, thePartproperty
set, a complete working mod, the four bundled sample mods (and the fact that the three playable
ones shipactive: 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 bundledsample_tetris3d
mod is the working equivalent); - LLMUnity throws
ArgumentException: Unknown platform Unixon 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+.
- the FullAccess demo's Start Tetris and the LuaMods demo's wave_started both throw,
WEBGL_BUILD_TROUBLESHOOTING.md—CS0103: WebGLInput does not exist:WebGLModule.dllis
added to the reference set only when the active build target is already WebGL, so a
#if UNITY_WEBGLguard 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 whatlink.xmlwas
verified to preserve.
Fixed
LUA_GAME_API.mdandFIRST_MOD.mdnow 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.mdstill described signals asNOT_IMPLEMENTEDstubs awaiting a
scheduler and the Unity binder as unwritten — both shipped long ago.DOCS_INDEX.mdomitted five docs that exist on disk.INSTALL.mdclaimed Lua runs under IL2CPP/WebGL "without extra stripping protection" while the
package ships alink.xmldoing exactly that.SHIPPING_PLAYER_MACHINES.mdnow 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
OnResponseReceivedhanded 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
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 (IsLocal → Host → Origin → 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 headless —
Instance.newproduced nothing in them.CoreAiHubDemo,LiveMechanicsDemo,LiveMechanicsModsChatDemo,WaveAutoBattlerModsDemo,MiniRpgModsDemoandModdableUnitsDemonow each carry a wiredRbxWorldHost. - 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
ChainResetpast the first line no longer verifies an audit log as intact. Truncating the tail and appending a forged restart used to reportOk.
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.
MutateAsyncdestroyed a role's memory when the load failed rather than being absent.game_config updatereported success when the store rejected the write.- WebGL:
Task.Delayin the endpoint drain loop never resumed and wedged activation forever; seven unguardedSwitchToThreadPoolcalls 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
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.
InstanceRegistrygained an engine-freeDiagnosticshook that reports an instance entering a tree the registry does not own. That path was previously an earlyreturn: 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
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 underResources/is packed into the player and the key is recoverable from the shipped build. ClearapiKey/secondaryApiKeyon committedResourcesassets and supply the key at runtime. WebGL key leaks inClientOwnedApi/ClientLimited/ServerManagedApifail the build too. ICoreAiComponentCommandExecutor.LastListedComponentsis removed, replaced byTryExecute(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 AssetsorCoreAI/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. OperationCanceledExceptionwas retried as a provider fault in three places; caller cancellation now propagates immediately.SetToolssilently did nothing on chains fronted byClientLimitedLlmClientDecoratororLoggingLlmClientDecorator. 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.jsoncorruption; non-atomic endpoint-registry saves; WebGLSwitchToThreadPoolhangs; 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 reportsfalsein the Editor even for a registered and enabled scene; the resultingAssert.Ignoreon the firstMoveNext()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.mdrecords 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 theFirecall, 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
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.
AgentPromptsInstallerchains theResources/AgentPrompts/Systemprovider 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 shippedProgrammer.txthad already drifted: it was missing the "answer plain questions directly — do NOT callread_skillor any tool for those" rule, thereport()/logic_*globals list, and theForbidden: io, os, require, load, loadfile, dofile, debugline. Every Unity host was therefore running an older Programmer prompt than the code said.The eight shadowing/dead assets are deleted (
PlayerChat.txtwas dead outright — the role id becamePlainChat), leavingDeveloperSampleAgent.txt, which has no const.Resources/AgentPrompts/Systemis 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 forCoreAIHub,CoreAIandCoreAiUnity.
Full EditMode suite: 2386 passed, 0 failed, 9 skipped (intentional).
CoreAI v6.6.0
Roblox → Rbx 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, notRoblox). Renamed every C# type, interface, member, test class and test namespace that carriedRobloxin its name to theRbxform —RobloxSpace→RbxSpace,RobloxWorldHost→RbxWorldHost,RobloxCameraFollower→RbxCameraFollower,IRobloxCameraRig→IRbxCameraRig,RobloxApiStubException→RbxApiStubException,LuaCsRoblox*→LuaCsRbx*, theRobloxApimember/namespace leaf→RbxApi, and allRoblox*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_*_CannotDisarmHandlerGuardguard 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 nestedmods_call. The bundled-seeder test and theBundledModSeederclass 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
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/InputChangedfiring(InputObject, gameProcessedEvent)with realRBXScriptConnection, the poll surface (IsKeyDown,GetKeysPressed,GetMouseLocation,MouseBehavior), andEnum.KeyCode/UserInputType/UserInputState/MouseBehaviorat exact Roblox names+values. Backed by a swappableIInputSourceseam; pumped once per frame before mod dispatch. workspace.CurrentCamera— a real Camera instance withCFrame/CameraType/CameraSubjectover a swappable camera‑rig seam, pluscamera_set_cframe/camera_followglobals. Reads ungated, writes WorldEdit‑gated.Part.Shape(Enum.PartType) —Ball,Cylinder(axis‑corrected mesh child),Wedge(custom 1‑unit ramp mesh + convex collider);CornerWedgeaccepted (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/reasoningdeltas 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/FindFirstChildWhichIsAnow search depth‑first (Roblox parity). - Services and the canonical Camera are locked against a mod removing them —
Destroy()errors,Clone()returns nil, reparenting errors, andClearAllChildren()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 (
RobloxWorldHostwired into the mods scope); Hub AI Settings placeholder/foldout fixes.
Performance
- Binder: per‑aspect property re‑apply (a
CFrame/Sizewrite skips full re‑materialization); cached Renderer/Collider/Rigidbody refs +MaterialPropertyBlock; cached primitive meshes/material. RbxScriptSignal.Firereuses the fire‑snapshot buffer; input signals pass a cached boxedfalse.- Input event objects gated on
HasConnections— a mouse‑move frame with no listener allocates noInputObject. RbxCFramemultiply/equality read struct fields directly (no per‑opfloat[12]).
Full changelog: Assets/CoreAI/CHANGELOG.md
CoreAI v6.2.1
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
versionbut left the
internalcom.neoxider.*dependency pins at6.0.0, so the CI "Package graph (lockstep + deps)" gate
failed with 11 mismatches. All six packages now pin the shared version. (supersedes thev6.2.0tag,
whose publishedpackage.jsonfiles still carried the stale6.0.0pins)
Added
tools/bump_version.py— one command bumps everyAssets/*/package.jsonversionand every
internalcom.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--checkto verify only).
Docs
- Root README audit: corrected the package count (six, including the new CoreAI MCP Server
package), fixed a wrong tool class name (WorldCommandTool→WorldLlmTool/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