{%- set template_version = "qwen-3.8-27b-chromix+froggerick.v1" %}
{#- -------------------------------------------------------------------------
qwen-3.8-27b-chromix+froggerick.v1
Tool-handling fork of qwen3.8-safe-v2.1-reasoning-compat.
Scope is intentionally limited to tool definitions, tool-call wire format,
tool-call history, tool arguments, parallel calls, and tool responses.
Non-tool conversation behavior, reasoning policy, role policy, multimodal
content handling, and generation-prompt behavior are kept aligned with the
safe template.
------------------------------------------------------------------------- -#}
{%- if not messages %}
{{- raise_exception('No messages provided.') }}
{%- endif %}
{#- -------------------------------------------------------------------------
Configuration
------------------------------------------------------------------------- -#}
{%- set _requested_tool_format =
tool_call_format if tool_call_format is defined else 'auto'
%}
{%- if _requested_tool_format not in ('auto', 'xml', 'json') %}
{{- raise_exception(
'Unexpected tool_call_format ' ~ _requested_tool_format ~
'. Supported values are auto (default), xml, and json.'
) }}
{%- endif %}
{%- set add_vision_id =
add_vision_id if add_vision_id is defined else false
%}
{%- set enable_thinking =
enable_thinking if enable_thinking is defined else true
%}
{%- set auto_disable_thinking_with_tools =
auto_disable_thinking_with_tools
if auto_disable_thinking_with_tools is defined
else false
%}
{%- if preserve_reasoning is defined
and preserve_reasoning is not none
and preserve_thinking is defined
and preserve_thinking is not none
and preserve_reasoning != preserve_thinking %}
{{- raise_exception(
'preserve_reasoning and preserve_thinking were both provided with conflicting values.'
) }}
{%- endif %}
{%- if preserve_reasoning is defined and preserve_reasoning is not none %}
{%- set _preserve_thinking = preserve_reasoning %}
{%- elif preserve_thinking is defined and preserve_thinking is not none %}
{%- set _preserve_thinking = preserve_thinking %}
{%- else %}
{%- set _preserve_thinking = true %}
{%- endif %}
{%- set max_tool_arg_chars =
max_tool_arg_chars if max_tool_arg_chars is defined else 0
%}
{%- set max_tool_response_chars =
max_tool_response_chars if max_tool_response_chars is defined else 0
%}
{%- if max_tool_arg_chars is not number or max_tool_arg_chars < 0 %}
{{- raise_exception('max_tool_arg_chars must be a non-negative number.') }}
{%- endif %}
{%- if max_tool_response_chars is not number or max_tool_response_chars < 0 %}
{{- raise_exception('max_tool_response_chars must be a non-negative number.') }}
{%- endif %}
{%- if tools is defined and tools is not none and tools %}
{%- if tools is string or tools is mapping or tools is not iterable %}
{{- raise_exception('tools must be an iterable list of tool definitions.') }}
{%- endif %}
{%- set _has_tools = true %}
{%- else %}
{%- set _has_tools = false %}
{%- endif %}
{#- -------------------------------------------------------------------------
Resolve tool-call wire format.
The safe template already switches auto mode to JSON when historical
OpenAI-compatible tool calls carry function.arguments as a JSON string.
That behavior is preserved.
This fork also switches auto mode to JSON when a historical tool call or
advertised tool name cannot be represented safely in Qwen's pseudo-XML
syntax, or when a string argument contains pseudo-XML control delimiters
that could terminate a parameter/function/tool_call block early.
Forced XML remains strict: structurally unsafe XML data raises instead of
being silently rewritten or corrupted.
------------------------------------------------------------------------- -#}
{%- set format_scan = namespace(
has_json_string_arguments=false,
has_xml_unsafe_data=false
) %}
{%- if _has_tools %}
{%- for tool in tools %}
{%- if tool.function is defined and tool.function is not none %}
{%- set _tool_def = tool.function %}
{%- else %}
{%- set _tool_def = tool %}
{%- endif %}
{%- if _tool_def.name is defined
and _tool_def.name is not none
and _tool_def.name is string %}
{%- set _tool_def_name = _tool_def.name %}
{%- if '<' in _tool_def_name
or '>' in _tool_def_name
or '\n' in _tool_def_name
or '\r' in _tool_def_name
or '\t' in _tool_def_name
or ' ' in _tool_def_name
or '=' in _tool_def_name %}
{%- set format_scan.has_xml_unsafe_data = true %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- endif %}
{%- for message in messages %}
{%- if message.role == 'assistant'
and message.tool_calls is defined
and message.tool_calls is not none
and message.tool_calls
and message.tool_calls is not string
and message.tool_calls is not mapping
and message.tool_calls is iterable %}
{%- for tool_call in message.tool_calls %}
{%- if tool_call.function is defined
and tool_call.function is not none %}
{%- set _tc = tool_call.function %}
{%- else %}
{%- set _tc = tool_call %}
{%- endif %}
{%- if _tc.name is defined
and _tc.name is not none
and _tc.name is string %}
{%- set _scan_name = _tc.name %}
{%- if '<' in _scan_name
or '>' in _scan_name
or '\n' in _scan_name
or '\r' in _scan_name
or '\t' in _scan_name
or ' ' in _scan_name
or '=' in _scan_name %}
{%- set format_scan.has_xml_unsafe_data = true %}
{%- endif %}
{%- endif %}
{%- if _tc.arguments is defined
and _tc.arguments is not none %}
{%- if _tc.arguments is string
and _tc.arguments | trim
and _tc.arguments | trim != '{}' %}
{%- set format_scan.has_json_string_arguments = true %}
{%- elif _tc.arguments is mapping %}
{%- for _scan_arg_name, _scan_arg_value in _tc.arguments | items %}
{%- set _scan_arg_name = _scan_arg_name | string %}
{%- if not _scan_arg_name
or '<' in _scan_arg_name
or '>' in _scan_arg_name
or '\n' in _scan_arg_name
or '\r' in _scan_arg_name
or '\t' in _scan_arg_name
or ' ' in _scan_arg_name
or '=' in _scan_arg_name %}
{%- set format_scan.has_xml_unsafe_data = true %}
{%- endif %}
{%- if _scan_arg_value is string
and (
'' in _scan_arg_value
or '' in _scan_arg_value
or '' in _scan_arg_value
or '' in _scan_arg_value
) %}
{%- set format_scan.has_xml_unsafe_data = true %}
{%- endif %}
{%- endfor %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- endif %}
{%- endfor %}
{%- if _requested_tool_format == 'auto' %}
{%- if format_scan.has_json_string_arguments
or format_scan.has_xml_unsafe_data %}
{%- set _tool_format = 'json' %}
{%- else %}
{%- set _tool_format = 'xml' %}
{%- endif %}
{%- else %}
{%- set _tool_format = _requested_tool_format %}
{%- endif %}
{%- set _thinking_enabled = enable_thinking %}
{%- if auto_disable_thinking_with_tools and _has_tools %}
{%- set _thinking_enabled = false %}
{%- endif %}
{%- set _effort_raw =
reasoning_effort if reasoning_effort is defined else 'medium'
%}
{%- if _effort_raw == 'none' %}
{%- set _reasoning_effort = 'none' %}
{%- set _thinking_enabled = false %}
{%- elif _effort_raw == 'high' or _effort_raw == 'xhigh' %}
{%- set _reasoning_effort = 'xhigh' %}
{%- elif _effort_raw == 'medium' %}
{%- set _reasoning_effort = 'medium' %}
{%- elif _effort_raw == 'low' %}
{%- set _reasoning_effort = 'low' %}
{%- else %}
{{- raise_exception(
'Unexpected reasoning effort ' ~ _effort_raw ~
'. Supported values are none, high/xhigh, medium, and low.'
) }}
{%- endif %}
{%- set reasoning_instructions = '' %}
{%- if _thinking_enabled %}
{%- if _reasoning_effort == 'xhigh' %}
{%- set reasoning_instructions =
'Reasoning effort is set to xhigh. Please think carefully through the task, validate key assumptions, consider plausible alternatives, and prioritize correctness, consistency, and clarity in the final answer.'
%}
{%- elif _reasoning_effort == 'low' %}
{%- set reasoning_instructions =
'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.'
%}
{%- endif %}
{%- endif %}
{#- -------------------------------------------------------------------------
Content rendering
------------------------------------------------------------------------- -#}
{%- set image_count = namespace(value=0) %}
{%- set video_count = namespace(value=0) %}
{%- macro render_content(content, do_vision_count, is_system_content=false) %}
{%- if content is string %}
{{- content }}
{%- elif content is iterable and content is not mapping %}
{%- for item in content %}
{%- if item is not mapping %}
{{- raise_exception(
'Content-list items must be mappings with a supported text, image, or video type.'
) }}
{%- endif %}
{%- set _item_type = item.type if 'type' in item else none %}
{%- if _item_type is not none
and _item_type not in ('text', 'image', 'image_url', 'video') %}
{{- raise_exception(
'Unexpected content item type ' ~ _item_type ~ '.'
) }}
{%- endif %}
{%- set _is_image =
_item_type == 'image'
or _item_type == 'image_url'
or 'image' in item
or 'image_url' in item
%}
{%- set _is_video =
_item_type == 'video'
or 'video' in item
%}
{%- if _is_image and _is_video %}
{{- raise_exception(
'A content item cannot contain both image and video data.'
) }}
{%- elif _item_type == 'text' and (_is_image or _is_video) %}
{{- raise_exception(
'A text content item cannot also contain image or video data.'
) }}
{%- elif _is_image %}
{%- if is_system_content %}
{{- raise_exception(
'System and developer messages cannot contain images.'
) }}
{%- endif %}
{%- if do_vision_count %}
{%- set image_count.value = image_count.value + 1 %}
{%- endif %}
{%- if add_vision_id %}
{{- 'Picture ' ~ image_count.value ~ ': ' }}
{%- endif %}
{{- '<|vision_start|><|image_pad|><|vision_end|>' }}
{%- elif _is_video %}
{%- if is_system_content %}
{{- raise_exception(
'System and developer messages cannot contain videos.'
) }}
{%- endif %}
{%- if do_vision_count %}
{%- set video_count.value = video_count.value + 1 %}
{%- endif %}
{%- if add_vision_id %}
{{- 'Video ' ~ video_count.value ~ ': ' }}
{%- endif %}
{{- '<|vision_start|><|video_pad|><|vision_end|>' }}
{%- elif _item_type == 'text' or 'text' in item %}
{%- if 'text' not in item or item.text is not string %}
{{- raise_exception(
'Text content items must contain a string text field.'
) }}
{%- endif %}
{{- item.text }}
{%- else %}
{{- raise_exception(
'Unexpected item in content list. Expected text, image, or video content.'
) }}
{%- endif %}
{%- endfor %}
{%- elif content is none or content is undefined %}
{{- '' }}
{%- else %}
{{- raise_exception('Unexpected content type.') }}
{%- endif %}
{%- endmacro %}
{#- -------------------------------------------------------------------------
Validate and merge leading system/developer messages.
Keep this strict: agent resilience must not silently reorder authority.
------------------------------------------------------------------------- -#}
{%- set head = namespace(count=0, seen_non_system=false) %}
{%- for message in messages %}
{%- set _is_system =
message.role == 'system' or message.role == 'developer'
%}
{%- if _is_system %}
{%- if head.seen_non_system %}
{{- raise_exception(
'System and developer messages must appear before all user, assistant, and tool messages.'
) }}
{%- endif %}
{%- set head.count = head.count + 1 %}
{%- else %}
{%- set head.seen_non_system = true %}
{%- endif %}
{%- endfor %}
{%- set system_state = namespace(content='') %}
{%- for message in messages[:head.count] %}
{%- set _part =
render_content(message.content, false, true) | trim
%}
{%- if _part %}
{%- if system_state.content %}
{%- set system_state.content =
system_state.content ~ '\n\n' ~ _part
%}
{%- else %}
{%- set system_state.content = _part %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- set _system_content = system_state.content %}
{%- set _msgs = messages[head.count:] %}
{#- -------------------------------------------------------------------------
System prompt and tool instructions
------------------------------------------------------------------------- -#}
{%- if _has_tools %}
{{- '<|im_start|>system\n' }}
{%- if reasoning_instructions %}
{{- reasoning_instructions ~ '\n\n' }}
{%- endif %}
{{- '# Tools\n\nYou have access to the following functions:\n\n' }}
{%- for tool in tools %}
{{- '\n' }}
{{- tool | tojson }}
{%- endfor %}
{{- '\n' }}
{%- if _tool_format == 'json' %}
{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n\n{"name": "example_function_name", "arguments": {"example_parameter_1": "value_1", "example_parameter_2": "value_2"}}\n\n\n\nReminder:\n- Use only function names and parameters defined in \n- Required parameters MUST be specified\n- Function calls MUST be a single JSON object with "name" and "arguments" inside \n- You may provide optional reasoning in natural language BEFORE the first tool call, but NOT after a tool call\n- For multiple or parallel calls, output one fully closed block per function, in the order they should be executed\n- Do NOT nest blocks\n- Do NOT output conversational text after a tool call\n- If no function call is needed, answer normally with your current knowledge\n' }}
{%- else %}
{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n\n\n\nvalue_1\n\n\nvalue_2\n\n\n\n\n\nReminder:\n- Use only function names and parameters defined in \n- Required parameters MUST be specified\n- Function calls MUST use an inner block inside \n- You may provide optional reasoning in natural language BEFORE the first tool call, but NOT after a tool call\n- and tags MUST begin at the start of a new line with no indentation\n- For multiple or parallel calls, output one fully closed block per function, in the order they should be executed\n- Do NOT nest blocks\n- Do NOT output conversational text after a tool call\n- If no function call is needed, answer normally with your current knowledge\n' }}
{%- endif %}
{%- if _system_content %}
{{- '\n\n' ~ _system_content }}
{%- endif %}
{{- '<|im_end|>\n' }}
{%- else %}
{%- if _system_content %}
{{- '<|im_start|>system\n'
~ (reasoning_instructions ~ '\n\n' if reasoning_instructions else '')
~ _system_content
~ '<|im_end|>\n'
}}
{%- elif reasoning_instructions %}
{{- '<|im_start|>system\n'
~ reasoning_instructions
~ '<|im_end|>\n'
}}
{%- endif %}
{%- endif %}
{#- -------------------------------------------------------------------------
Find the last real user query.
Preserve the safe-template behavior for normal conversations. The only
exception is a retained tool continuation where context truncation has
removed the original user query. In that tool-specific case, use the last
wrapped tool_response/user turn when available, otherwise the final retained
message index. This prevents tool loops from dying solely because the
initiating user turn fell out of context.
------------------------------------------------------------------------- -#}
{%- set tool_history = namespace(
has_activity=false,
last_wrapped_tool_response_index=none
) %}
{%- set ns = namespace(
multi_step_tool=true,
last_query_index=(_msgs | length) - 1
) %}
{%- for message in _msgs %}
{%- if message.role == 'tool' %}
{%- set tool_history.has_activity = true %}
{%- elif message.role == 'assistant'
and message.tool_calls is defined
and message.tool_calls is not none
and message.tool_calls %}
{%- set tool_history.has_activity = true %}
{%- elif message.role == 'user' %}
{%- set _tool_scan_user = render_content(message.content, false) | trim %}
{%- if _tool_scan_user.startswith('')
and _tool_scan_user.endswith('') %}
{%- set tool_history.has_activity = true %}
{%- set tool_history.last_wrapped_tool_response_index = loop.index0 %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- for message in _msgs[::-1] %}
{%- set index = (_msgs | length - 1) - loop.index0 %}
{%- if ns.multi_step_tool and message.role == 'user' %}
{%- set _rendered_user =
render_content(message.content, false) | trim
%}
{%- if not (
_rendered_user.startswith('')
and _rendered_user.endswith('')
) %}
{%- set ns.multi_step_tool = false %}
{%- set ns.last_query_index = index %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- if ns.multi_step_tool %}
{%- if tool_history.has_activity %}
{%- if tool_history.last_wrapped_tool_response_index is not none %}
{%- set ns.last_query_index = tool_history.last_wrapped_tool_response_index %}
{%- else %}
{%- set ns.last_query_index = (_msgs | length) - 1 %}
{%- endif %}
{%- set ns.multi_step_tool = false %}
{%- else %}
{{- raise_exception('No user query found in messages.') }}
{%- endif %}
{%- endif %}
{#- -------------------------------------------------------------------------
Conversation rendering
------------------------------------------------------------------------- -#}
{%- set history_state = namespace(previous_role='') %}
{%- for message in _msgs %}
{%- set content =
render_content(message.content, true) | trim
%}
{%- if message.role == 'user' %}
{{- '<|im_start|>user\n'
~ content
~ '<|im_end|>\n'
}}
{%- elif message.role == 'assistant' %}
{%- set reasoning_content = '' %}
{%- if message.reasoning_content is defined
and message.reasoning_content is not none %}
{%- if message.reasoning_content is string %}
{%- set reasoning_content = message.reasoning_content %}
{%- else %}
{%- set reasoning_content =
message.reasoning_content | string
%}
{%- endif %}
{%- elif message.thinking is defined
and message.thinking is not none %}
{%- if message.thinking is string %}
{%- set reasoning_content = message.thinking %}
{%- else %}
{%- set reasoning_content =
message.thinking | string
%}
{%- endif %}
{%- elif message.reasoning is defined
and message.reasoning is not none %}
{#- vLLM's OpenAI-compatible reasoning parser may return the
historical thinking text under `reasoning`. Accept it only as
a fallback so the established reasoning_content/thinking
precedence and rendered prompt format remain unchanged. -#}
{%- if message.reasoning is string %}
{%- set reasoning_content = message.reasoning %}
{%- else %}
{%- set reasoning_content =
message.reasoning | string
%}
{%- endif %}
{%- endif %}
{%- set reasoning_content = reasoning_content | trim %}
{#- Preserve the original invariant: when thinking is preserved,
always reconstruct the thinking block, even when it is empty. -#}
{%- if _preserve_thinking
or loop.index0 > ns.last_query_index %}
{{- '<|im_start|>assistant\n\n'
~ reasoning_content
~ '\n\n\n'
~ content
}}
{%- else %}
{{- '<|im_start|>assistant\n' ~ content }}
{%- endif %}
{%- if message.tool_calls is defined
and message.tool_calls is not none
and message.tool_calls %}
{%- if message.tool_calls is string
or message.tool_calls is mapping
or message.tool_calls is not iterable %}
{{- raise_exception(
'assistant.tool_calls must be an iterable list of tool calls.'
) }}
{%- endif %}
{%- for tool_call in message.tool_calls %}
{%- if tool_call.function is defined
and tool_call.function is not none %}
{%- set tc = tool_call.function %}
{%- else %}
{%- set tc = tool_call %}
{%- endif %}
{%- if tc.name is not defined
or tc.name is none
or tc.name is not string
or not tc.name %}
{{- raise_exception(
'Every tool call must have a non-empty string name.'
) }}
{%- endif %}
{%- set tc_name = tc.name %}
{%- if _tool_format == 'json' %}
{%- if loop.first %}
{%- if content | trim %}
{{- '\n\n\n' }}
{%- else %}
{{- '\n' }}
{%- endif %}
{%- else %}
{{- '\n\n' }}
{%- endif %}
{%- set _json_arguments = '{}' %}
{%- if tc.arguments is defined
and tc.arguments is not none %}
{%- if tc.arguments is mapping %}
{%- set _json_arguments =
tc.arguments | tojson
%}
{%- elif tc.arguments is string %}
{%- set _raw_arguments =
tc.arguments | trim
%}
{%- if _raw_arguments %}
{%- if not (
_raw_arguments.startswith('{')
and _raw_arguments.endswith('}')
) %}
{{- raise_exception(
'JSON tool-call arguments must be a JSON object string.'
) }}
{%- endif %}
{%- set _json_arguments =
_raw_arguments
%}
{%- endif %}
{%- else %}
{{- raise_exception(
'JSON tool-call arguments must be a mapping or a JSON object string.'
) }}
{%- endif %}
{%- endif %}
{{- '{"name": ' }}
{{- tc_name | tojson }}
{{- ', "arguments": ' }}
{{- _json_arguments }}
{{- '}\n' }}
{%- else %}
{%- if '<' in tc_name
or '>' in tc_name
or '\n' in tc_name
or '\r' in tc_name
or '\t' in tc_name
or ' ' in tc_name
or '=' in tc_name %}
{{- raise_exception(
'XML tool-call names cannot contain angle brackets, spaces, equals signs, or control whitespace.'
) }}
{%- endif %}
{%- if loop.first %}
{%- if content | trim %}
{{- '\n\n\n\n'
}}
{%- else %}
{{- '\n\n'
}}
{%- endif %}
{%- else %}
{{- '\n\n\n'
}}
{%- endif %}
{%- if tc.arguments is defined
and tc.arguments is not none %}
{%- if tc.arguments is mapping %}
{%- for args_name, args_value
in tc.arguments | items %}
{%- set _argument_name =
args_name | string
%}
{%- if not _argument_name
or '<' in _argument_name
or '>' in _argument_name
or '\n' in _argument_name
or '\r' in _argument_name
or '\t' in _argument_name
or ' ' in _argument_name
or '=' in _argument_name %}
{{- raise_exception(
'XML tool parameter names must be non-empty and cannot contain angle brackets, spaces, equals signs, or control whitespace.'
) }}
{%- endif %}
{{- '\n'
}}
{%- if args_value is string %}
{%- set _argument_value =
args_value
%}
{%- if _tool_format == 'xml'
and (
'' in _argument_value
or '' in _argument_value
or '' in _argument_value
or '' in _argument_value
) %}
{{- raise_exception(
'XML tool argument contains a reserved tool-control delimiter. Leave tool_call_format unset so auto mode can select JSON, or use tool_call_format="json".'
) }}
{%- endif %}
{%- else %}
{%- set _argument_value =
args_value | tojson
%}
{%- endif %}
{%- if max_tool_arg_chars > 0
and _argument_value | length
> max_tool_arg_chars %}
{{- _argument_value[:max_tool_arg_chars] }}
{{- '\n[TRUNCATED — original length '
~ (_argument_value | length | string)
~ ' chars]'
}}
{%- else %}
{{- _argument_value }}
{%- endif %}
{{- '\n\n' }}
{%- endfor %}
{%- elif tc.arguments is string %}
{%- set _raw_arguments =
tc.arguments | trim
%}
{%- if _raw_arguments
and _raw_arguments != '{}' %}
{{- raise_exception(
'tool_call_format="xml" requires tool-call arguments to be mappings, but received a JSON string. Parse the JSON string into a mapping before applying the template, or leave tool_call_format unset so the template can select the JSON tool-call format automatically.'
) }}
{%- endif %}
{%- else %}
{{- raise_exception(
'XML tool-call arguments must be a mapping. Parse JSON-string arguments before applying the template.'
) }}
{%- endif %}
{%- endif %}
{{- '\n' }}
{%- endif %}
{%- endfor %}
{%- endif %}
{{- '<|im_end|>\n' }}
{%- elif message.role == 'tool' %}
{%- if history_state.previous_role != 'tool' %}
{{- '<|im_start|>user' }}
{%- endif %}
{%- if max_tool_response_chars > 0
and content | length > max_tool_response_chars %}
{%- set content =
content[:max_tool_response_chars]
~ '\n[TRUNCATED — original length '
~ (content | length | string)
~ ' chars]'
%}
{%- endif %}
{{- '\n\n' }}
{{- content }}
{{- '\n' }}
{%- if loop.last %}
{{- '<|im_end|>\n' }}
{%- elif _msgs[loop.index0 + 1].role != 'tool' %}
{{- '<|im_end|>\n' }}
{%- endif %}
{%- elif message.role == 'system'
or message.role == 'developer' %}
{{- raise_exception(
'System and developer messages must appear only at the beginning of the conversation.'
) }}
{%- else %}
{{- raise_exception(
'Unexpected message role ' ~ message.role ~ '.'
) }}
{%- endif %}
{%- set history_state.previous_role = message.role %}
{%- endfor %}
{#- -------------------------------------------------------------------------
Generation prompt
------------------------------------------------------------------------- -#}
{%- if add_generation_prompt %}
{{- '<|im_start|>assistant\n' }}
{%- if not _thinking_enabled %}
{{- '\n\n\n\n' }}
{%- else %}
{{- '\n' }}
{%- endif %}
{%- endif %}