Repository navigation
Conversation
A plugin tool's answer reached the agent as one JSON text block, so a base64 PNG was a long string the model read as characters. Now a tool result with a top-level `imageContent` array goes out as MCP image content, after the rest of the result as text. Each entry must be a PNG, JPEG, WebP or GIF of at most 5 MB, and images stop before the reply reaches the 8 MB cap; one left out is named in a last text block. Such a result goes without `structuredContent`: Codex shows the model only that (no images) when it is there, and Claude Code shows it in place of the texts. Was zeronsh#1362.
A plugin service's Luau heap is 64 MB, and a plugin can't ask for more.
A design tool's service runs out at around 40k nodes.
"limits": { "memory_mb": 256 } gives its service that much, 512 at
most. More than 512, or anything that isn't a whole number from 1 to
512, makes the manifest broken rather than clamped, so the Allow sheet
never shows a number that isn't what runs. The consent record carries
memory_mb only when it's asked, so other plugins' digests don't change.
The Allow sheet names the number on the background line. Raising it asks
again, and lowering it doesn't.
A service with nothing in flight and more than half its memory in use
now runs a full collection. Luau collects only as it allocates and never
before failing an allocation, so the garbage of one big call counted
against the next, which then ran out.
Was zeronsh#1363.
…h an "eval" permission Was zeronsh#1366.
A plugin's service had no way to measure text: it runs in the engine, which linked no text shaping, and only a window's canvas could measure. Layout that must work while Zeron is hidden (agent tools) couldn't run. zeron.measure_text(text, opts) shapes with zgx-gpu's TextServices, the same shaper and font lookup a window's canvas uses, over the system's fonts and the app's own. zeron.load_font(path) adds a font file from the plugin's folder, so the service and a window that loads the same file with ui.load_font measure alike. Also: - Plugins: zeron.load_font says when the plugin has no such file - Plugins: the engine measures text with zgx-text, without zgx's renderer - Plugins: zeron.load_font takes a font's bytes in base64 Was zeronsh#1367.
No manifest permission granted zgx's Capability::Fonts, so every plugin window's ui.load_font was refused, and a window couldn't measure in the fonts its service loads with zeron.load_font. A loaded font reaches every window's text, Zeron's own included, so the person is asked. Was zeronsh#1378.
…in base64
A body crossed into Luau as String::from_utf8_lossy, so every byte that
isn't UTF-8 became U+FFFD: a fetched TTF or PNG came back corrupted, and a
plugin had no way to download one. With { binary = true } the body is the
bytes in base64 (Luau gets results as JSON, which carries text only). The
default stays text.
Was zeronsh#1379.
This was referenced Nov 12, 2026
Closed
…ull request The plugin APIs above need zgx changes that are one pull request now, zeronsh/zgx#2110: Capability::Fonts and ui.load_font for the "fonts" permission, and the zgx-text crate the engine measures with. The engine's zgx and zgx-text and every zgx crate apps/zgx takes (its [patch] entries too) are pinned to its head on the author's fork, 99e17852, so a service and its windows measure with the same zgx. Once #2110 merges, the pins go back to zeronsh/zgx.
hoangvu12
force-pushed
the
plugin-design-apis
branch
from
November 13, 2026 00:56
059d97e to
b824a40
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This replaces seven pull requests with one, as asked, so the plugin APIs can be reviewed together. We're building a design tool as a Luau plugin, and each commit adds one thing its service, its windows or its agent needs. Each commit is one of the old pull requests, in the order they build on each other, and its message says which.
zeron.toolresult with animageContentarray reaches the agent as MCP image contentlimits.memory_mb), shown on the consent sheetzeron.evalruns scripts the plugin's agents write, in its service, behind an"eval"permissionzeron.measure_textandzeron.load_fontin services, measuring as a window's canvas does (zgx-text, no renderer)"fonts"permission grants zgx'sCapability::Fonts, so a plugin's windows can callui.load_fontzeron.fetchwithbinary = truereturns a response's bytes whole, in base64zeron.db, the same SQLite file its windows open (newcrates/plugin-db)apps/zgxpinned to one zgx, the combined zgx pull requestThe old pull requests' descriptions still explain each change in full, with their own testing.
Needs zeronsh/zgx#2110
The fonts permission needs
Capability::Fontsand the engine needs thezgx-textcrate. Both are in zeronsh/zgx#2110, the combined zgx pull request. The last commit pins the engine'szgxandzgx-text, and every zgx crateapps/zgxtakes (its[patch]entries too), to that pull request's head on my fork,99e17852. Once #2110 merges, the pins go back tozeronsh/zgx.CI
CI on
zeron/zgxis red for every pull request right now, from three breakages in the base branch, none of them in these files:zeron-uidoesn't compile its tests:E0283 type annotations neededatcrates/ui/src/state.rs:5987andcrates/ui/src/transcript.rs:12347. It failslinux-ui / ui-tests,macos-nativeandwindows / tests, as on CI for zeron/zgx: integration branch, zgx suite on plan and admission, faster betas #1357 (ui-tests).libc::rusageandgetrusagein test code atcrates/engine/src/chat_persistence.rs:1200andcrates/engine/src/source_control.rs:4869(from 6f4e0e5) don't exist, which failswindows / tests, also on CI for zeron/zgx: integration branch, zgx suite on plan and admission, faster betas #1357 (windows). zgx Windows: browser, terminal, annotation and intro fixes #1219 fixes both of these.zeron_v2_is_in_step_with_the_defaultfailszgx-linuxbecause c153906 changedscreens/panel/init.luauwithout bringing Zeron v2 in step. zgx: Zeron v2's panel gets the active-tab wash fix, so the v2 staleness test passes #1382 fixes that.The macOS zgx job also fails GPU tests (
create_render_pipeline 'shader fill') on #1382, which only touches v2's template files, so those come from the runner, not from a change.Testing
On Windows, against
zeron/zgxat c153906 with the pins above:cargo check --locked: the engine andzeron-zgxwith its tests are clean.cargo test -p zeron-engine --lib plugins: 239 passed. It needs therusagegate from zgx Windows: browser, terminal, annotation and intro fixes #1219 to compile the engine's tests on Windows, which I applied locally and didn't commit.cargo test -p zeron-mcp --lib: 74 passed.cargo test -p zeron-plugin-db: 5 passed, 1 ignored.zeron-zgxtests filtered toplugins::grants,consent,localeandi18n: 9, 8, 3 and 4 passed.Two conflicts came up and both kept both sides: #1366 and #1363 add consent-sheet strings, manifest checks and service limits in the same places, and #1380 and #1367 each add a row to the same table in
apps/zgx/docs/plugins.md.