Module: Legion::LLM::Inference::NativeToolLoop

Included in:
Executor
Defined in:
lib/legion/llm/inference/native_tool_loop.rb

Constant Summary collapse

QWEN_TOOL_USE_RE =

Tag-based markup some Qwen variants emit when a tool is selected via the chat template instead of being returned through the tool_calls field. Captures one block per tool call:

<tool_use_name>NAME</tool_use_name>
(<tool_use_parameter>KEY</tool_use_parameter>
<tool_use_value>VALUE</tool_use_value>)+
%r{
  <tool_use_name>(?<name>[^<]+)</tool_use_name>
  (?<body>(?:\s*<tool_use_parameter>[^<]+</tool_use_parameter>
               \s*<tool_use_value>[^<]*</tool_use_value>)*)
}mx
QWEN_PARAM_RE =
%r{
  <tool_use_parameter>(?<param>[^<]+)</tool_use_parameter>
  \s*<tool_use_value>(?<value>[^<]*)</tool_use_value>
}mx
LEAKED_TOKEN_RE =

Leaked chat-template tool-call token some models (e.g. gemma via vLLM) emit as literal text instead of the structured tool_calls field. One block per tool call; captured live from the ledger (2026-07):

<|tool_call>call:NAME{key:<|"|>value<|"|>,key2:<|"|>value2<|"|>}<tool_call|>

LEAKED_TOKEN_RE captures NAME + the raw .. body; LEAKED_TOKEN_ARG_RE walks the body as key:<|"|>value<|"|> pairs. The value capture is non-greedy and terminated only by the <|"|> delimiter, so embedded regular quotes and newlines (common in browser code: args) survive — a gsub-to-quotes + parse-as-object approach would break on those.

/<\|tool_call>call:(?<name>[^{]+?)(?<body>\{.*?\})<tool_call\|>/m
LEAKED_TOKEN_ARG_RE =
/(?<key>\w+):<\|"\|>(?<value>.*?)<\|"\|>/m