* docs(gateway): document llamacpp toolSchemaProfile for custom llama.cpp endpoints
Custom openai-completions providers pointed at a llama.cpp / llama-server
endpoint bypass the GBNF-safe schema normalization that built-in llama-cpp,
ollama, and lmstudio providers apply automatically. The toolSchemaProfile:
"llamacpp" switch activates it, but the supported value was never named in
the docs, so users hit llama.cpp 400 'failed to parse grammar' on tools with
large minLength/maxLength (e.g. cron trigger.script, maxLength 65536).
- Expand the toolSchemaProfile row to name the values recognized on a model's
compat (llamacpp, gemini) and when llamacpp must be set explicitly;
cross-reference the unsupportedToolSchemaKeywords escape hatch.
- Add a 'Local models (llama.cpp / llama-server)' provider example showing
the required compat.toolSchemaProfile: "llamacpp" on a custom endpoint.
Related to #117070
Co-Authored-By: iCodeMate <noreply@anthropic.com>
* docs(gateway): describe llamacpp profile as stripping, not clamping
Address review feedback on #117120: the fallback sentence claimed the
llamacpp profile "also clamps" constraints, but cleanSchemaForLlamacppGbnf
only removes `pattern` outright and drops `maxLength` at or above the
2000-repetition threshold (LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD). It
never clamps a value, and small bounds like `minLength: 1` are preserved
(confirmed by the projection test at src/plugin-sdk/provider-tools.test.ts).
Reword the escape-hatch sentence to describe the implemented stripping
behavior and contrast it with the unconditional keyword-list drops, so
operators do not expect a preserved bounded constraint.
No code or behavior changes; documentation only.
* docs(gateway): scope llamacpp profile description to its actual transformations
Address follow-up review on #117120: the toolSchemaProfile table row
described `llamacpp` as "rewriting tool schemas into the JSON Schema
subset llama.cpp can compile to GBNF," which overstates what
cleanSchemaForLlamacppGbnf does. The cleaner only removes `pattern`
outright and drops `maxLength` at or above the 2000-repetition threshold
(LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD); it leaves every other keyword
and `minLength` untouched, and those are not guaranteed GBNF-safe.
Reword the row to state the exact transformation contract and explicitly
note it is a targeted compatibility cleaner, not a blanket GBNF-safety
guarantee. No code or behavior changes; documentation only.
Co-Authored-By: iCodeMate <noreply@anthropic.com>
* docs(gateway): tighten llama.cpp profile contract
* docs(gateway): order local model examples
---------
Co-authored-by: iCodeMate <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(clickclack): answer thread replies past the server thread-reply window
Thread replies stopped being answered once a ClickClack thread passed 100
replies, with no reply, no transcript entry, no gateway warning, and no
replay after reconnect.
The gateway resolved a thread.reply_created event by fetching the whole
thread and searching its reply list. The ClickClack thread endpoint caps
that response at 100 earliest replies by default, so reply 101 was absent,
the lookup returned null, and the event was treated as handled while the
websocket cursor advanced past it. A DM thread reply was worse: it hit the
DM branch first, and thread replies never appear in the root DM timeline
that branch pages, so every DM thread reply was dropped.
Resolve the event's own message_id through the authoritative single-message
endpoint the plugin already uses, which collapses the three window
heuristics into one canonical path. Transient failures still propagate so
reconnect replays them; only a 404 resolves to unreadable, and that now
records an operator warning instead of counting as a handled event.
* test(clickclack): harden reply recovery proof
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
The drain test asserted "close has not settled" after a fixed 20ms sleep.
Node only exempts a connection from close()'s idle sweep once its parser has
begun a message, so a client-side connect barrier let a loaded machine reach
close() before the server parsed the request: the socket was swept as idle,
the client saw ECONNRESET, and the drain settled inside the window.
Wait on capture admission (onRequestStart) instead, which fires server-side
after the headers are accepted, and move the assertion to just before the
successor is used so it proves the successor was minted mid-drain.
* fix(cli): update plugins doctor clean message (#115073)
Root cause: plugins doctor reports 'No plugin issues detected.' even when a selected context-engine plugin is quarantined at runtime, because doctor is a fast static control-plane check.
Architectural owner: plugins-cli.runtime.ts
Canonical fix: Change clean status message to direct operators to 'openclaw health' for active runtime quarantine/fallback status.
Production LOC delta: +2 LOC
* fix(cli): update plugins doctor clean message wording (#115073)
Root cause: Refine the diagnostic text message to run openclaw health directly.
Architectural owner: src/cli/plugins-cli.runtime.ts
* fix(cli): clarify plugin doctor scope
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(plugin-sdk): project recorded health facts through computed account status
* fix(plugin-sdk): regenerate API baseline and pin ingressUnavailable literal in test
* fix(qa): update Codex auth fixture protocol version
* test(qa): bind Codex auth fixture to runtime version
* test(qa): load Codex fixture version through public surface
* fix(plugins): filter .d.mts and .d.cts declaration files in extension discovery
isExtensionFile only checked for .d.ts but not .d.mts or .d.cts.
path.extname('.d.mts') returns '.mts' so these declaration files
passed through all checks and were treated as valid plugin entries.
Replaced the single .d.ts check with a regex covering all TS
declaration file variants.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update d.mts test to use distinct filenames so it fails on old code
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(exec): preserve approved exec continuation output
Approved async exec continuations reused the compact background notification
formatter, so the agent resumed from the last 400 characters of output with all
whitespace collapsed and the head silently dropped.
Both hosts now render the continuation through a shared whitespace-preserving
formatter bounded at 16,000 UTF-16 units. Compact `notifyOnExit` notifications,
poll/retained output, and the gateway diagnostics branch are unchanged.
The truncation marker deliberately reports no exact omission count: output can
already be capped at capture time without leaving a marker, so an exact number
would describe only this cut while reading as though nothing else was lost.
Closes#41152
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2d9762e2-f967-4cdd-9895-299512a20114
* fix(exec): secure approved continuation handoff
* test(exec): cover authenticated approval handoff
* fix(exec): retain approved followup delivery ownership
* fix(exec): retain compact continuation fallback
* fix(exec): bound accepted followup observation
* fix(exec): keep observer diagnostics internal
---------
Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2d9762e2-f967-4cdd-9895-299512a20114