mateclaw/mateclaw-server/src/test/java/vip/mate/agent
matevip 07eb625d11 fix(agent): collapse SystemMessages at egress to fix LM Studio 400 (#218)
Some OpenAI-compatible providers (LM Studio's built-in server, certain
strict-mode vLLM / SGLang deployments) reject 400 "System message must
be at the beginning" when SystemMessages appear after user / assistant
/ tool messages. The reasoning loop currently emits four SystemMessage
segments — main prompt at index 0, skill catalog inserted at index 1,
progress-ledger snapshot and stale-reminder appended at the end of
nonHistoryPrefix after the runtime-context UserMessage. The latter two
violate the strict shape, so conversations on LM Studio 400 on the
first turn (reported in #218).

Add MessageNormalizer: collects every SystemMessage in the outbound
prompt regardless of position, joins their text with a blank-line
separator, and emits a single SystemMessage at index 0. Non-system
messages keep their relative order, so AssistantMessage(tool_calls) ↔
ToolResponseMessage adjacency is preserved verbatim (required by strict
pair validators).

Wire it into doStreamCall as the first pre-egress step so every node
(reasoning, step-execution, summarizing, plan-generation, limit-exceeded)
inherits the fix without per-node changes, and any future node that
emits multiple SystemMessages stays compliant.

The transformation is semantically equivalent on permissive providers
(OpenAI, DashScope, Ollama, DeepSeek, Kimi, Doubao, GLM) — the merged
token sequence matches what they would have seen across N SystemMessages
— and safe on non-OpenAI protocols (Anthropic, Vertex / Gemini), whose
adapters already extract SystemMessages into a top-level system field
and receive an identical payload.

Kill switch: -Dmateclaw.llm.message-normalizer.enabled=false reverts to
the prior behavior for emergency rollback.

Tests: 11 unit tests on MessageNormalizer cover empty / no-system /
canonical / mid-list / tail / blanks / tool-pair preservation / Prompt
option-reference preservation / kill switch. 1 wiring test pins the
call site in doStreamCall. Full vip.mate.agent.** suite (504 tests)
stays green.

Closes #218.
2026-05-25 17:57:03 +08:00
..
binding feat(skill): automatic lifecycle archival for idle skills 2026-05-19 09:55:59 +08:00
context feat(agent): age-based compaction of older tool-response bodies 2026-05-24 23:00:11 +08:00
delegation chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00
graph fix(agent): collapse SystemMessages at egress to fix LM Studio 400 (#218) 2026-05-25 17:57:03 +08:00
progress feat(agent): inject stale-ledger reminder when the model stops updating 2026-05-24 23:00:35 +08:00
service chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00
AgentAuthoringToolTest.java feat(agent): digital-employee builder skill to auto-create agents and chain them into a workflow (#165) 2026-05-21 16:26:04 +08:00
AgentGraphBuilderBasePathResolutionTest.java fix(tool): close three sandbox follow-up gaps surfaced by review 2026-05-25 17:55:56 +08:00
AgentGraphBuilderPreferenceTest.java chore: sync multiple commits from private dev 2026-04-19 18:37:44 +08:00
AgentServiceUniquenessTest.java chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00
AgentToolSetTest.java chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00
BaseAgentApprovalSanitizationTest.java chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00
BaseAgentCronIsolationTest.java fix(cron): isolate scheduled-job runs from shared conversation (#142) 2026-05-17 07:58:10 +08:00
BaseAgentDirectToolHistoryScrubTest.java chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00
BaseAgentHeadOrphanRepairTest.java fix(agent): make head-orphan repair order-sensitive — a later same-id assistant does not redeem an earlier orphan 2026-05-13 09:03:16 +08:00
BaseAgentMultimodalSkipNoticeTest.java chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00
BaseAgentToolCallReplayTest.java fix(agent): structured tool-call replay + final-answer-only content (#120) 2026-05-14 07:46:30 +08:00
GraphEventPublisherIterationTest.java chore(test): backfill mateclaw-server/src/test/ that earlier PRIVATE_ITEMS pattern accidentally excluded 2026-05-12 17:38:08 +08:00