mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-06-18 20:29:11 -04:00
refactor: Finalize agent template
This commit is contained in:
@@ -34,9 +34,8 @@ QString AgentConfig::validate(const AgentConfig &config)
|
||||
return QStringLiteral("Agent config '%1' has no model").arg(config.name);
|
||||
if (config.endpoint.isEmpty())
|
||||
return QStringLiteral("Agent config '%1' has no endpoint").arg(config.name);
|
||||
if (config.messageFormat.isEmpty()) {
|
||||
return QStringLiteral("Agent config '%1' has no [template].message_format")
|
||||
.arg(config.name);
|
||||
if (config.body.isEmpty()) {
|
||||
return QStringLiteral("Agent config '%1' has no [body]").arg(config.name);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ struct AgentConfig
|
||||
QString providerInstance;
|
||||
QString model;
|
||||
QString endpoint;
|
||||
QString role;
|
||||
QString systemPrompt;
|
||||
QStringList tags;
|
||||
|
||||
struct Match
|
||||
@@ -40,10 +40,7 @@ struct AgentConfig
|
||||
bool enableThinking = false;
|
||||
bool enableTools = false;
|
||||
|
||||
QString messageFormat;
|
||||
QJsonObject sampling;
|
||||
QJsonObject thinking;
|
||||
QString context;
|
||||
QJsonObject body;
|
||||
QString extendsName;
|
||||
bool abstract = false;
|
||||
bool hidden = false;
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
#include "AgentFactory.hpp"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLoggingCategory>
|
||||
#include <QThread>
|
||||
|
||||
@@ -37,6 +42,7 @@ AgentFactory::AgentFactory(
|
||||
, m_secrets(secrets)
|
||||
{
|
||||
::initAgentsResource();
|
||||
loadModelOverrides();
|
||||
reload();
|
||||
}
|
||||
|
||||
@@ -169,7 +175,11 @@ Agent *AgentFactory::create(const QString &name, QObject *parent, QString *error
|
||||
*cfg, m_instanceFactory.data(), m_secrets.data(), errorOut);
|
||||
if (!provider)
|
||||
return nullptr;
|
||||
auto agent = std::make_unique<Agent>(*cfg, provider, /*parent=*/nullptr);
|
||||
AgentConfig resolved = *cfg;
|
||||
const QString modelOv = m_modelOverrides.value(resolved.name);
|
||||
if (!modelOv.isEmpty())
|
||||
resolved.model = modelOv;
|
||||
auto agent = std::make_unique<Agent>(resolved, provider, /*parent=*/nullptr);
|
||||
if (!agent->isValid()) {
|
||||
if (errorOut)
|
||||
*errorOut = agent->invalidReason();
|
||||
@@ -193,6 +203,9 @@ Agent *AgentFactory::createFromFile(
|
||||
*cfgOpt, m_instanceFactory.data(), m_secrets.data(), errorOut);
|
||||
if (!provider)
|
||||
return nullptr;
|
||||
const QString modelOv = m_modelOverrides.value(cfgOpt->name);
|
||||
if (!modelOv.isEmpty())
|
||||
cfgOpt->model = modelOv;
|
||||
auto agent = std::make_unique<Agent>(std::move(*cfgOpt), provider, /*parent=*/nullptr);
|
||||
if (!agent->isValid()) {
|
||||
if (errorOut) *errorOut = agent->invalidReason();
|
||||
@@ -221,4 +234,55 @@ Providers::ProviderSecretsStore *AgentFactory::secretsStore() const noexcept
|
||||
return m_secrets.data();
|
||||
}
|
||||
|
||||
QString AgentFactory::modelOverride(const QString &agentName) const
|
||||
{
|
||||
return m_modelOverrides.value(agentName);
|
||||
}
|
||||
|
||||
void AgentFactory::setModelOverride(const QString &agentName, const QString &model)
|
||||
{
|
||||
if (model.isEmpty())
|
||||
m_modelOverrides.remove(agentName);
|
||||
else
|
||||
m_modelOverrides.insert(agentName, model);
|
||||
saveModelOverrides();
|
||||
}
|
||||
|
||||
namespace {
|
||||
QString modelOverridesPath()
|
||||
{
|
||||
return Core::ICore::userResourcePath(QStringLiteral("qodeassist/config/agent_models.json"))
|
||||
.toFSPathString();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void AgentFactory::loadModelOverrides()
|
||||
{
|
||||
m_modelOverrides.clear();
|
||||
QFile f(modelOverridesPath());
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
const QJsonObject obj = QJsonDocument::fromJson(f.readAll()).object();
|
||||
for (auto it = obj.constBegin(); it != obj.constEnd(); ++it) {
|
||||
const QString model = it.value().toString();
|
||||
if (!model.isEmpty())
|
||||
m_modelOverrides.insert(it.key(), model);
|
||||
}
|
||||
}
|
||||
|
||||
void AgentFactory::saveModelOverrides() const
|
||||
{
|
||||
const QString path = modelOverridesPath();
|
||||
QDir().mkpath(QFileInfo(path).absolutePath());
|
||||
QJsonObject obj;
|
||||
for (auto it = m_modelOverrides.constBegin(); it != m_modelOverrides.constEnd(); ++it)
|
||||
obj.insert(it.key(), it.value());
|
||||
QFile f(path);
|
||||
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
LOG_MESSAGE(QStringLiteral("[Agents] cannot write model overrides: %1").arg(path));
|
||||
return;
|
||||
}
|
||||
f.write(QJsonDocument(obj).toJson(QJsonDocument::Indented));
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -53,12 +53,22 @@ public:
|
||||
void registerConfig(AgentConfig config);
|
||||
void clear();
|
||||
|
||||
// Per-agent model chosen in QodeAssist settings. The agent TOML's `model`
|
||||
// is only the default; an override here (keyed by agent name) wins and is
|
||||
// applied when the agent is built. Empty model clears the override.
|
||||
[[nodiscard]] QString modelOverride(const QString &agentName) const;
|
||||
void setModelOverride(const QString &agentName, const QString &model);
|
||||
|
||||
[[nodiscard]] Providers::ProviderInstanceFactory *instanceFactory() const noexcept;
|
||||
[[nodiscard]] Providers::ProviderSecretsStore *secretsStore() const noexcept;
|
||||
|
||||
private:
|
||||
void loadModelOverrides();
|
||||
void saveModelOverrides() const;
|
||||
|
||||
std::vector<AgentConfig> m_configs;
|
||||
QHash<QString, qsizetype> m_indexByName;
|
||||
QHash<QString, QString> m_modelOverrides;
|
||||
QStringList m_errors;
|
||||
QStringList m_warnings;
|
||||
QPointer<Providers::ProviderInstanceFactory> m_instanceFactory;
|
||||
|
||||
@@ -120,8 +120,7 @@ AgentConfig configFromMerged(const QJsonObject &obj)
|
||||
cfg.providerInstance = obj.value("provider_instance").toString();
|
||||
cfg.model = obj.value("model").toString();
|
||||
cfg.endpoint = obj.value("endpoint").toString();
|
||||
cfg.role = obj.value("role").toString();
|
||||
cfg.context = obj.value("context").toString();
|
||||
cfg.systemPrompt = obj.value("system_prompt").toString();
|
||||
cfg.enableThinking = obj.value("enable_thinking").toBool(false);
|
||||
cfg.enableTools = obj.value("enable_tools").toBool(false);
|
||||
cfg.tags = stringArray(obj.value("tags"));
|
||||
@@ -135,10 +134,7 @@ AgentConfig configFromMerged(const QJsonObject &obj)
|
||||
cfg.abstract = obj.value("abstract").toBool(false);
|
||||
cfg.hidden = obj.value("hidden").toBool(false);
|
||||
|
||||
const QJsonObject tpl = obj.value("template").toObject();
|
||||
cfg.messageFormat = tpl.value("message_format").toString();
|
||||
cfg.sampling = tpl.value("sampling").toObject();
|
||||
cfg.thinking = tpl.value("thinking").toObject();
|
||||
cfg.body = obj.value("body").toObject();
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,46 @@
|
||||
<RCC>
|
||||
<qresource prefix="/agents">
|
||||
<file>partials/openai_messages.jinja</file>
|
||||
<file>partials/openai_assistant.jinja</file>
|
||||
<file>partials/openai_tool_results.jinja</file>
|
||||
<file>partials/openai_user.jinja</file>
|
||||
<file>partials/openai_image_content.jinja</file>
|
||||
<file>partials/openai_responses_input.jinja</file>
|
||||
<file>partials/anthropic_messages.jinja</file>
|
||||
<file>partials/anthropic_image.jinja</file>
|
||||
<file>partials/google_contents.jinja</file>
|
||||
<file>partials/google_part.jinja</file>
|
||||
<file>partials/ollama_messages.jinja</file>
|
||||
|
||||
<file>chat_base.toml</file>
|
||||
<file>openai_base_chat.toml</file>
|
||||
<file>openai_responses_base.toml</file>
|
||||
<file>anthropic_base_chat.toml</file>
|
||||
<file>google_base_chat.toml</file>
|
||||
<file>ollama_base_chat.toml</file>
|
||||
<file>ollama_base_fim.toml</file>
|
||||
|
||||
<file>openai_chat.toml</file>
|
||||
<file>openai_compatible_chat.toml</file>
|
||||
<file>openai_responses.toml</file>
|
||||
<file>mistral_chat.toml</file>
|
||||
<file>mistral_medium_chat.toml</file>
|
||||
<file>mistral_reasoning_chat.toml</file>
|
||||
<file>codestral_chat.toml</file>
|
||||
<file>codestral_fim.toml</file>
|
||||
<file>llamacpp_chat.toml</file>
|
||||
<file>lmstudio_chat.toml</file>
|
||||
<file>lmstudio_responses.toml</file>
|
||||
<file>openrouter_chat.toml</file>
|
||||
<file>ollama_openai_chat.toml</file>
|
||||
<file>ollama_gemma4_e4b_chat.toml</file>
|
||||
<file>ollama_codellama_7b_code_fim.toml</file>
|
||||
<file>ollama_codellama_13b_qml_fim.toml</file>
|
||||
|
||||
<file>claude_sonnet_chat.toml</file>
|
||||
<file>claude_sonnet46_chat.toml</file>
|
||||
<file>claude_haiku45_chat.toml</file>
|
||||
<file>claude_opus_max.toml</file>
|
||||
<file>google_gemini_chat.toml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
19
sources/agents/anthropic_base_chat.toml
Normal file
19
sources/agents/anthropic_base_chat.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "Anthropic Base Chat"
|
||||
description = "Anthropic Messages API request body (/v1/messages). Abstract — extend it and set model."
|
||||
abstract = true
|
||||
extends = "Chat Base"
|
||||
|
||||
provider_instance = "Claude"
|
||||
endpoint = "/v1/messages"
|
||||
enable_tools = true
|
||||
tags = ["chat", "claude", "anthropic", "cloud"]
|
||||
|
||||
[body]
|
||||
max_tokens = 8192
|
||||
temperature = 1
|
||||
system = """{% if existsIn(ctx, "system_prompt") %}{{ tojson(ctx.system_prompt) }}{% endif %}"""
|
||||
messages = """
|
||||
[ {% include "partials/anthropic_messages.jinja" %} ]
|
||||
"""
|
||||
16
sources/agents/chat_base.toml
Normal file
16
sources/agents/chat_base.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "Chat Base"
|
||||
description = "Shared system prompt for coding-chat agents. Abstract — not selectable."
|
||||
abstract = true
|
||||
|
||||
system_prompt = """
|
||||
You are a helpful coding assistant integrated into Qt Creator.
|
||||
Answer concisely. Prefer concrete diffs or minimal patches over rewriting
|
||||
whole files. Use markdown code blocks with language tags.
|
||||
|
||||
{% if file_exists("${PROJECT_DIR}/README.md") %}
|
||||
## Project README.md
|
||||
{{ read_file("${PROJECT_DIR}/README.md") }}
|
||||
{% endif %}
|
||||
"""
|
||||
14
sources/agents/claude_haiku45_chat.toml
Normal file
14
sources/agents/claude_haiku45_chat.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "Anthropic Base Chat"
|
||||
name = "Claude Haiku 4.5 Chat"
|
||||
description = "Anthropic Claude Haiku 4.5 — fastest model with near-frontier intelligence; extended thinking (manual budget)."
|
||||
|
||||
model = "claude-haiku-4-5-20251001"
|
||||
|
||||
enable_thinking = true
|
||||
tags = ["chat", "claude", "anthropic", "cloud", "haiku", "fast"]
|
||||
|
||||
[body]
|
||||
max_tokens = 16000
|
||||
thinking = { type = "enabled", budget_tokens = 4096 }
|
||||
15
sources/agents/claude_opus_max.toml
Normal file
15
sources/agents/claude_opus_max.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "Anthropic Base Chat"
|
||||
name = "Claude Opus 4.8 Max"
|
||||
description = "Anthropic Claude Opus 4.8 at maximum capability — adaptive thinking at max effort, 128k max output."
|
||||
|
||||
model = "claude-opus-4-8"
|
||||
|
||||
enable_thinking = true
|
||||
tags = ["chat", "claude", "anthropic", "cloud", "opus", "max"]
|
||||
|
||||
[body]
|
||||
max_tokens = 128000
|
||||
thinking = { type = "adaptive", display = "summarized" }
|
||||
output_config = { effort = "max" }
|
||||
15
sources/agents/claude_sonnet46_chat.toml
Normal file
15
sources/agents/claude_sonnet46_chat.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "Anthropic Base Chat"
|
||||
name = "Claude Sonnet 4.6 Chat"
|
||||
description = "Anthropic Claude Sonnet 4.6 — fast, capable coding chat with adaptive thinking."
|
||||
|
||||
model = "claude-sonnet-4-6"
|
||||
|
||||
enable_thinking = true
|
||||
tags = ["chat", "claude", "anthropic", "cloud", "sonnet"]
|
||||
|
||||
[body]
|
||||
max_tokens = 16000
|
||||
thinking = { type = "adaptive", display = "summarized" }
|
||||
output_config = { effort = "high" }
|
||||
@@ -1,77 +1,14 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "Anthropic Base Chat"
|
||||
name = "Claude Sonnet Chat"
|
||||
description = "Anthropic Claude (Messages API) — coding chat assistant via the hosted Claude provider."
|
||||
|
||||
provider_instance = "Claude"
|
||||
endpoint = "/v1/messages"
|
||||
description = "Anthropic Claude Sonnet 4.6 (Messages API) — coding chat assistant with thinking."
|
||||
|
||||
model = "claude-sonnet-4-6"
|
||||
|
||||
role = """
|
||||
You are a helpful coding assistant integrated into Qt Creator.
|
||||
Answer concisely. When the user shares code, prefer concrete diffs or
|
||||
minimal patches over rewriting whole files. Use markdown code blocks
|
||||
with language tags so the IDE can render them.
|
||||
"""
|
||||
|
||||
enable_thinking = true
|
||||
enable_tools = true
|
||||
|
||||
tags = ["chat", "claude", "anthropic", "cloud"]
|
||||
|
||||
context = """
|
||||
{%- set readme = read_file("${PROJECT_DIR}/README.md") -%}
|
||||
{%- if length(readme) > 0 %}
|
||||
## Project README.md
|
||||
{{ readme }}
|
||||
{%- endif %}
|
||||
"""
|
||||
|
||||
[template]
|
||||
message_format = """
|
||||
{
|
||||
{%- if existsIn(ctx, "system_prompt") %}
|
||||
"system": {{ tojson(ctx.system_prompt) }},
|
||||
{%- endif %}
|
||||
"messages": [
|
||||
{%- for msg in ctx.history %}
|
||||
{
|
||||
"role": {{ tojson(msg.role) }},
|
||||
"content": [
|
||||
{%- for b in msg.content_blocks %}
|
||||
{%- if b.type == "image" %}
|
||||
{
|
||||
"type": "image",
|
||||
"source": {
|
||||
{%- if b.is_url %}
|
||||
"type": "url",
|
||||
"url": {{ tojson(b.data) }}
|
||||
{%- else %}
|
||||
"type": "base64",
|
||||
"media_type": {{ tojson(b.media_type) }},
|
||||
"data": {{ tojson(b.data) }}
|
||||
{%- endif %}
|
||||
}
|
||||
}{% if not loop.is_last %},{% endif %}
|
||||
{%- else %}
|
||||
{{ tojson(b) }}{% if not loop.is_last %},{% endif %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
]
|
||||
}{% if not loop.is_last %},{% endif %}
|
||||
{%- endfor %}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
[template.sampling]
|
||||
max_tokens = 8192
|
||||
temperature = 1
|
||||
|
||||
[template.thinking.overrides]
|
||||
temperature = 1
|
||||
|
||||
[template.thinking.request_block.thinking]
|
||||
type = "enabled"
|
||||
budget_tokens = 4096
|
||||
[body]
|
||||
max_tokens = 8192
|
||||
thinking = { type = "enabled", budget_tokens = 4096 }
|
||||
|
||||
11
sources/agents/codestral_chat.toml
Normal file
11
sources/agents/codestral_chat.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "Codestral Chat"
|
||||
description = "Mistral Codestral (Chat Completions API) — coding chat assistant."
|
||||
|
||||
provider_instance = "Codestral"
|
||||
endpoint = "/v1/chat/completions"
|
||||
model = "codestral-latest"
|
||||
|
||||
tags = ["chat", "codestral", "mistral", "cloud"]
|
||||
19
sources/agents/codestral_fim.toml
Normal file
19
sources/agents/codestral_fim.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "Codestral FIM"
|
||||
description = "Mistral Codestral fill-in-the-middle code completion (/v1/fim/completions)."
|
||||
|
||||
provider_instance = "Mistral AI"
|
||||
endpoint = "/v1/fim/completions"
|
||||
model = "codestral-latest"
|
||||
|
||||
enable_thinking = false
|
||||
enable_tools = false
|
||||
tags = ["fim", "codestral", "mistral", "cloud", "completion"]
|
||||
|
||||
[body]
|
||||
max_tokens = 256
|
||||
temperature = 0.2
|
||||
stream = true
|
||||
prompt = """{{ tojson(ctx.prefix) }}"""
|
||||
suffix = """{% if existsIn(ctx, "suffix") %}{{ tojson(ctx.suffix) }}{% endif %}"""
|
||||
20
sources/agents/google_base_chat.toml
Normal file
20
sources/agents/google_base_chat.toml
Normal file
@@ -0,0 +1,20 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "Google Base Chat"
|
||||
description = "Google Gemini generateContent request body. Abstract — extend it and set model/endpoint."
|
||||
abstract = true
|
||||
extends = "Chat Base"
|
||||
|
||||
provider_instance = "Google AI"
|
||||
enable_tools = true
|
||||
tags = ["chat", "gemini", "google", "cloud"]
|
||||
|
||||
[body]
|
||||
system_instruction = """{% if existsIn(ctx, "system_prompt") %}{ "parts": [ { "text": {{ tojson(ctx.system_prompt) }} } ] }{% endif %}"""
|
||||
contents = """
|
||||
[ {% include "partials/google_contents.jinja" %} ]
|
||||
"""
|
||||
|
||||
[body.generationConfig]
|
||||
maxOutputTokens = 8192
|
||||
temperature = 1
|
||||
@@ -1,79 +1,15 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "Google Base Chat"
|
||||
name = "Gemini Chat"
|
||||
description = "Google Gemini (generateContent API) — coding chat assistant via the hosted Google AI provider."
|
||||
description = "Google Gemini 2.5 Flash (generateContent API) — coding chat with thinking."
|
||||
|
||||
provider_instance = "Google AI"
|
||||
endpoint = "/models/gemini-2.5-flash:streamGenerateContent?alt=sse"
|
||||
|
||||
model = "gemini-2.5-flash"
|
||||
|
||||
role = """
|
||||
You are a helpful coding assistant integrated into Qt Creator.
|
||||
Answer concisely. When the user shares code, prefer concrete diffs or
|
||||
minimal patches over rewriting whole files. Use markdown code blocks
|
||||
with language tags so the IDE can render them.
|
||||
"""
|
||||
endpoint = "/models/gemini-2.5-flash:streamGenerateContent?alt=sse"
|
||||
model = "gemini-2.5-flash"
|
||||
|
||||
enable_thinking = true
|
||||
enable_tools = true
|
||||
|
||||
tags = ["chat", "gemini", "google", "cloud"]
|
||||
|
||||
context = """
|
||||
{%- set readme = read_file("${PROJECT_DIR}/README.md") -%}
|
||||
{%- if length(readme) > 0 %}
|
||||
## Project README.md
|
||||
{{ readme }}
|
||||
{%- endif %}
|
||||
"""
|
||||
|
||||
[template]
|
||||
message_format = """
|
||||
{
|
||||
{%- if existsIn(ctx, "system_prompt") %}
|
||||
"system_instruction": { "parts": [{ "text": {{ tojson(ctx.system_prompt) }} }] },
|
||||
{%- endif %}
|
||||
"contents": [
|
||||
{%- for msg in ctx.history %}
|
||||
{
|
||||
"role": {% if msg.role == "assistant" %}"model"{% else %}"user"{% endif %},
|
||||
"parts": [
|
||||
{%- for b in msg.content_blocks %}
|
||||
{%- if b.type == "text" %}
|
||||
{ "text": {{ tojson(b.text) }} }
|
||||
{%- else if b.type == "thinking" %}
|
||||
{ "text": {{ tojson(b.thinking) }}, "thought": true, "thoughtSignature": {{ tojson(b.signature) }} }
|
||||
{%- else if b.type == "tool_use" %}
|
||||
{ "functionCall": { "name": {{ tojson(b.name) }}, "args": {{ tojson(b.input) }} } }
|
||||
{%- else if b.type == "tool_result" %}
|
||||
{ "functionResponse": { "name": {{ tojson(b.name) }}, "response": { "result": {{ tojson(b.content) }} } } }
|
||||
{%- else if b.type == "image" %}
|
||||
{%- if b.is_url %}
|
||||
{ "file_data": { "mime_type": {{ tojson(b.media_type) }}, "file_uri": {{ tojson(b.data) }} } }
|
||||
{%- else %}
|
||||
{ "inline_data": { "mime_type": {{ tojson(b.media_type) }}, "data": {{ tojson(b.data) }} } }
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
{ "text": "" }
|
||||
{%- endif %}
|
||||
{% if not loop.is_last %},{% endif %}
|
||||
{%- endfor %}
|
||||
]
|
||||
}{% if not loop.is_last %},{% endif %}
|
||||
{%- endfor %}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
[template.sampling.generationConfig]
|
||||
maxOutputTokens = 8192
|
||||
temperature = 1
|
||||
|
||||
[template.thinking.request_block.generationConfig]
|
||||
temperature = 1
|
||||
[body.generationConfig]
|
||||
maxOutputTokens = 16000
|
||||
|
||||
[template.thinking.request_block.generationConfig.thinkingConfig]
|
||||
includeThoughts = true
|
||||
thinkingBudget = 8192
|
||||
thinkingConfig = { includeThoughts = true, thinkingBudget = 8192 }
|
||||
|
||||
11
sources/agents/llamacpp_chat.toml
Normal file
11
sources/agents/llamacpp_chat.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "llama.cpp Chat"
|
||||
description = "llama.cpp server (OpenAI-compatible Chat Completions) — local coding chat assistant."
|
||||
|
||||
provider_instance = "llama.cpp"
|
||||
endpoint = "/v1/chat/completions"
|
||||
model = "llama"
|
||||
|
||||
tags = ["chat", "llamacpp", "local"]
|
||||
11
sources/agents/lmstudio_chat.toml
Normal file
11
sources/agents/lmstudio_chat.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "LM Studio Chat"
|
||||
description = "LM Studio (Chat Completions API) — local coding chat assistant."
|
||||
|
||||
provider_instance = "LM Studio (Chat Completions)"
|
||||
endpoint = "/v1/chat/completions"
|
||||
model = "local-model"
|
||||
|
||||
tags = ["chat", "lmstudio", "local"]
|
||||
11
sources/agents/lmstudio_responses.toml
Normal file
11
sources/agents/lmstudio_responses.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Responses Base"
|
||||
name = "LM Studio Responses"
|
||||
description = "LM Studio (Responses API) — local coding chat assistant."
|
||||
|
||||
provider_instance = "LM Studio (Responses API)"
|
||||
endpoint = "/v1/responses"
|
||||
model = "local-model"
|
||||
|
||||
tags = ["chat", "lmstudio", "responses", "local"]
|
||||
11
sources/agents/mistral_chat.toml
Normal file
11
sources/agents/mistral_chat.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "Mistral Chat"
|
||||
description = "Mistral Large (Chat Completions API) — coding chat assistant."
|
||||
|
||||
provider_instance = "Mistral AI"
|
||||
endpoint = "/v1/chat/completions"
|
||||
model = "mistral-large-latest"
|
||||
|
||||
tags = ["chat", "mistral", "cloud"]
|
||||
11
sources/agents/mistral_medium_chat.toml
Normal file
11
sources/agents/mistral_medium_chat.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "Mistral Medium Chat"
|
||||
description = "Mistral Medium 3.5 (Chat Completions API) — frontier coding/agentic chat."
|
||||
|
||||
provider_instance = "Mistral AI"
|
||||
endpoint = "/v1/chat/completions"
|
||||
model = "mistral-medium-latest"
|
||||
|
||||
tags = ["chat", "mistral", "medium", "cloud"]
|
||||
12
sources/agents/mistral_reasoning_chat.toml
Normal file
12
sources/agents/mistral_reasoning_chat.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "Mistral Reasoning Chat"
|
||||
description = "Mistral Magistral Medium — native chain-of-thought reasoning model."
|
||||
|
||||
provider_instance = "Mistral AI"
|
||||
endpoint = "/v1/chat/completions"
|
||||
model = "magistral-medium-latest"
|
||||
|
||||
enable_thinking = true
|
||||
tags = ["chat", "mistral", "reasoning", "cloud"]
|
||||
@@ -1,44 +1,21 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "Ollama Base Chat"
|
||||
description = "Shared base for Ollama /api/chat profiles."
|
||||
|
||||
abstract = true
|
||||
description = "Ollama native /api/chat request body. Abstract — extend it and set model/options."
|
||||
abstract = true
|
||||
extends = "Chat Base"
|
||||
|
||||
provider_instance = "Ollama (Native)"
|
||||
endpoint = "/api/chat"
|
||||
|
||||
tags = ["ollama", "local"]
|
||||
|
||||
[template]
|
||||
message_format = """
|
||||
{
|
||||
"messages": [
|
||||
{%- if existsIn(ctx, "system_prompt") %}
|
||||
{
|
||||
"role": "system",
|
||||
"content": {{ tojson(ctx.system_prompt) }}
|
||||
}{% if length(ctx.history) > 0 %},{% endif %}
|
||||
{%- endif %}
|
||||
{%- for msg in ctx.history %}
|
||||
{
|
||||
"role": {{ tojson(msg.role) }},
|
||||
"content": {{ tojson(msg.content) }}{% if existsIn(msg, "images") %},
|
||||
"images": [
|
||||
{%- for img in msg.images %}
|
||||
{{ tojson(img.data) }}{% if not loop.is_last %},{% endif %}
|
||||
{%- endfor %}
|
||||
]{% endif %}
|
||||
}{% if not loop.is_last %},{% endif %}
|
||||
{%- endfor %}
|
||||
]
|
||||
}
|
||||
[body]
|
||||
stream = true
|
||||
messages = """
|
||||
[ {% include "partials/ollama_messages.jinja" %} ]
|
||||
"""
|
||||
|
||||
[template.sampling]
|
||||
stream = true
|
||||
|
||||
[template.sampling.options]
|
||||
[body.options]
|
||||
num_predict = 2048
|
||||
temperature = 0.7
|
||||
keep_alive = "5m"
|
||||
|
||||
@@ -1,30 +1,18 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "Ollama FIM Base"
|
||||
description = "Shared base for Ollama native FIM (/api/generate) profiles."
|
||||
|
||||
abstract = true
|
||||
description = "Ollama native /api/generate FIM request body. Abstract — extend it and set model/prompt."
|
||||
abstract = true
|
||||
|
||||
provider_instance = "Ollama (Native)"
|
||||
endpoint = "/api/generate"
|
||||
|
||||
tags = ["ollama", "local", "fim"]
|
||||
|
||||
[template]
|
||||
message_format = """
|
||||
{
|
||||
"prompt": {{ tojson(ctx.prefix) }},
|
||||
"suffix": {{ tojson(ctx.suffix) }}
|
||||
{%- if existsIn(ctx, "system_prompt") %},
|
||||
"system": {{ tojson(ctx.system_prompt) }}
|
||||
{%- endif %}
|
||||
}
|
||||
"""
|
||||
|
||||
[template.sampling]
|
||||
[body]
|
||||
stream = true
|
||||
system = """{% if existsIn(ctx, "system_prompt") %}{{ tojson(ctx.system_prompt) }}{% endif %}"""
|
||||
|
||||
[template.sampling.options]
|
||||
[body.options]
|
||||
num_predict = 512
|
||||
temperature = 0.2
|
||||
top_p = 0.9
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "Ollama FIM Base"
|
||||
name = "Qt CodeLlama 13B QML FIM"
|
||||
description = "Local Qt-Company-tuned CodeLlama 13B for QML FIM completion."
|
||||
|
||||
provider_instance = "Ollama (Native)"
|
||||
endpoint = "/api/generate"
|
||||
|
||||
model = "theqtcompany/codellama-13b-qml:latest"
|
||||
|
||||
tags = ["fim", "ollama", "local", "codellama", "qml", "qt"]
|
||||
@@ -13,28 +11,12 @@ tags = ["fim", "ollama", "local", "codellama", "qml", "qt"]
|
||||
[match]
|
||||
file_patterns = ["*.qml"]
|
||||
|
||||
[template]
|
||||
message_format = """
|
||||
{
|
||||
"prompt": {%- if existsIn(ctx, "suffix") and length(ctx.suffix) > 0 -%}
|
||||
{{ tojson("<SUF>" + ctx.suffix + "<PRE>" + ctx.prefix + "<MID>") }}
|
||||
{%- else -%}
|
||||
{{ tojson("<PRE>" + ctx.prefix + "<MID>") }}
|
||||
{%- endif %}
|
||||
{%- if existsIn(ctx, "system_prompt") %},
|
||||
"system": {{ tojson(ctx.system_prompt) }}
|
||||
{%- endif %}
|
||||
}
|
||||
"""
|
||||
[body]
|
||||
prompt = """{% if existsIn(ctx, "suffix") and length(ctx.suffix) > 0 %}{{ tojson("<SUF>" + ctx.suffix + "<PRE>" + ctx.prefix + "<MID>") }}{% else %}{{ tojson("<PRE>" + ctx.prefix + "<MID>") }}{% endif %}"""
|
||||
|
||||
[template.sampling]
|
||||
stream = true
|
||||
|
||||
[template.sampling.options]
|
||||
[body.options]
|
||||
num_predict = 500
|
||||
temperature = 0
|
||||
top_p = 1
|
||||
repeat_penalty = 1.05
|
||||
keep_alive = "5m"
|
||||
|
||||
stop = ["<SUF>", "<PRE>", "</PRE>", "</SUF>", "< EOT >", "\\end", "<MID>", "</MID>", "##"]
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "Ollama FIM Base"
|
||||
name = "CodeLlama 7B Code FIM"
|
||||
description = "Local CodeLlama 7B (code variant) on Ollama, FIM completion via PRE/SUF/MID markers."
|
||||
|
||||
provider_instance = "Ollama (Native)"
|
||||
endpoint = "/api/generate"
|
||||
|
||||
model = "codellama:7b-code"
|
||||
|
||||
tags = ["fim", "ollama", "local", "codellama"]
|
||||
@@ -13,22 +11,8 @@ tags = ["fim", "ollama", "local", "codellama"]
|
||||
[match]
|
||||
file_patterns = ["*.cpp", "*.cc", "*.cxx", "*.c", "*.h", "*.hpp", "*.hxx", "*.inl"]
|
||||
|
||||
[template]
|
||||
message_format = """
|
||||
{
|
||||
"prompt": {{ tojson("<PRE> " + ctx.prefix + " <SUF>" + ctx.suffix + " <MID>") }}
|
||||
{%- if existsIn(ctx, "system_prompt") %},
|
||||
"system": {{ tojson(ctx.system_prompt) }}
|
||||
{%- endif %}
|
||||
}
|
||||
"""
|
||||
[body]
|
||||
prompt = """{{ tojson("<PRE> " + ctx.prefix + " <SUF>" + ctx.suffix + " <MID>") }}"""
|
||||
|
||||
[template.sampling]
|
||||
stream = true
|
||||
|
||||
[template.sampling.options]
|
||||
num_predict = 512
|
||||
temperature = 0.2
|
||||
top_p = 0.9
|
||||
keep_alive = "5m"
|
||||
[body.options]
|
||||
stop = ["<EOT>", "<PRE>", "<SUF>", "<MID>"]
|
||||
|
||||
@@ -1,34 +1,16 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "Ollama gemma4:e4b Chat"
|
||||
extends = "Ollama Base Chat"
|
||||
|
||||
extends = "Ollama Base Chat"
|
||||
name = "Ollama gemma4:e4b Chat"
|
||||
description = "Local Gemma 4 E4B on Ollama /api/chat — coding chat assistant."
|
||||
|
||||
model = "gemma4:e4b"
|
||||
|
||||
role = """
|
||||
You are a helpful coding assistant integrated into Qt Creator.
|
||||
Answer concisely. When the user shares code, prefer concrete diffs or
|
||||
minimal patches over rewriting whole files. Use markdown code blocks
|
||||
with language tags so the IDE can render them.
|
||||
"""
|
||||
|
||||
enable_thinking = true
|
||||
enable_tools = true
|
||||
|
||||
tags = ["chat", "ollama", "local", "gemma"]
|
||||
|
||||
context = """
|
||||
{%- set readme = read_file("${PROJECT_DIR}/README.md") -%}
|
||||
|
||||
{%- if length(readme) > 0 %}
|
||||
## Project README.md
|
||||
{{ readme }}
|
||||
{%- endif %}
|
||||
"""
|
||||
|
||||
[template.sampling.options]
|
||||
[body.options]
|
||||
num_predict = 4096
|
||||
temperature = 1
|
||||
top_k = 64
|
||||
|
||||
11
sources/agents/ollama_openai_chat.toml
Normal file
11
sources/agents/ollama_openai_chat.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "Ollama (OpenAI-compatible) Chat"
|
||||
description = "Ollama via its OpenAI-compatible Chat Completions endpoint — local coding chat assistant."
|
||||
|
||||
provider_instance = "Ollama (OpenAI-compatible)"
|
||||
endpoint = "/v1/chat/completions"
|
||||
model = "qwen2.5-coder"
|
||||
|
||||
tags = ["chat", "ollama", "local"]
|
||||
18
sources/agents/openai_base_chat.toml
Normal file
18
sources/agents/openai_base_chat.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "OpenAI Base Chat"
|
||||
description = "OpenAI Chat Completions request body. Abstract — extend it and set provider/endpoint/model."
|
||||
abstract = true
|
||||
extends = "Chat Base"
|
||||
|
||||
provider_instance = "OpenAI (Chat Completions)"
|
||||
endpoint = "/chat/completions"
|
||||
enable_tools = true
|
||||
tags = ["chat", "openai", "cloud"]
|
||||
|
||||
[body]
|
||||
max_tokens = 8192
|
||||
temperature = 0.7
|
||||
messages = """
|
||||
[ {% include "partials/openai_messages.jinja" %} ]
|
||||
"""
|
||||
7
sources/agents/openai_chat.toml
Normal file
7
sources/agents/openai_chat.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "OpenAI Chat"
|
||||
description = "OpenAI Chat Completions — coding chat assistant (GPT-4o)."
|
||||
|
||||
model = "gpt-4o"
|
||||
10
sources/agents/openai_compatible_chat.toml
Normal file
10
sources/agents/openai_compatible_chat.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "OpenAI Compatible Chat"
|
||||
description = "Any OpenAI-compatible Chat Completions endpoint — set the model to match your server."
|
||||
|
||||
provider_instance = "OpenAI Compatible"
|
||||
model = "default"
|
||||
|
||||
tags = ["chat", "openai", "compatible"]
|
||||
7
sources/agents/openai_responses.toml
Normal file
7
sources/agents/openai_responses.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Responses Base"
|
||||
name = "OpenAI Responses"
|
||||
description = "OpenAI Responses API (/responses) — coding chat assistant."
|
||||
|
||||
model = "gpt-4o"
|
||||
19
sources/agents/openai_responses_base.toml
Normal file
19
sources/agents/openai_responses_base.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
schema_version = 1
|
||||
|
||||
name = "OpenAI Responses Base"
|
||||
description = "OpenAI Responses API request body (/responses). Abstract — extend it and set provider/endpoint/model."
|
||||
abstract = true
|
||||
extends = "Chat Base"
|
||||
|
||||
provider_instance = "OpenAI (Responses API)"
|
||||
endpoint = "/responses"
|
||||
enable_tools = true
|
||||
tags = ["chat", "openai", "responses", "cloud"]
|
||||
|
||||
[body]
|
||||
max_output_tokens = 8192
|
||||
temperature = 0.7
|
||||
instructions = """{% if existsIn(ctx, "system_prompt") %}{{ tojson(ctx.system_prompt) }}{% endif %}"""
|
||||
input = """
|
||||
[ {% include "partials/openai_responses_input.jinja" %} ]
|
||||
"""
|
||||
11
sources/agents/openrouter_chat.toml
Normal file
11
sources/agents/openrouter_chat.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
schema_version = 1
|
||||
|
||||
extends = "OpenAI Base Chat"
|
||||
name = "OpenRouter Chat"
|
||||
description = "OpenRouter (OpenAI-compatible Chat Completions) — coding chat assistant."
|
||||
|
||||
provider_instance = "OpenRouter"
|
||||
endpoint = "/chat/completions"
|
||||
model = "openai/gpt-4o"
|
||||
|
||||
tags = ["chat", "openrouter", "cloud"]
|
||||
9
sources/agents/partials/anthropic_image.jinja
Normal file
9
sources/agents/partials/anthropic_image.jinja
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "image",
|
||||
"source":
|
||||
{% if b.is_url %}
|
||||
{ "type": "url", "url": {{ tojson(b.data) }} }
|
||||
{% else %}
|
||||
{ "type": "base64", "media_type": {{ tojson(b.media_type) }}, "data": {{ tojson(b.data) }} }
|
||||
{% endif %}
|
||||
},
|
||||
12
sources/agents/partials/anthropic_messages.jinja
Normal file
12
sources/agents/partials/anthropic_messages.jinja
Normal file
@@ -0,0 +1,12 @@
|
||||
{% for msg in ctx.history %}
|
||||
{
|
||||
"role": {{ tojson(msg.role) }},
|
||||
"content": [
|
||||
{% for b in msg.content_blocks %}
|
||||
{% if b.type == "image" %}{% include "partials/anthropic_image.jinja" %}
|
||||
{% else %}{{ tojson(b) }},
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
]
|
||||
},
|
||||
{% endfor %}
|
||||
6
sources/agents/partials/google_contents.jinja
Normal file
6
sources/agents/partials/google_contents.jinja
Normal file
@@ -0,0 +1,6 @@
|
||||
{% for msg in ctx.history %}
|
||||
{
|
||||
"role": {% if msg.role == "assistant" %}"model"{% else %}"user"{% endif %},
|
||||
"parts": [ {% for b in msg.content_blocks %}{% include "partials/google_part.jinja" %}{% endfor %} ]
|
||||
},
|
||||
{% endfor %}
|
||||
17
sources/agents/partials/google_part.jinja
Normal file
17
sources/agents/partials/google_part.jinja
Normal file
@@ -0,0 +1,17 @@
|
||||
{% if b.type == "text" %}
|
||||
{ "text": {{ tojson(b.text) }} },
|
||||
{% else if b.type == "thinking" %}
|
||||
{ "text": {{ tojson(b.thinking) }}, "thought": true, "thoughtSignature": {{ tojson(b.signature) }} },
|
||||
{% else if b.type == "tool_use" %}
|
||||
{ "functionCall": { "name": {{ tojson(b.name) }}, "args": {{ tojson(b.input) }} } },
|
||||
{% else if b.type == "tool_result" %}
|
||||
{ "functionResponse": { "name": {{ tojson(b.name) }}, "response": { "result": {{ tojson(b.content) }} } } },
|
||||
{% else if b.type == "image" %}
|
||||
{% if b.is_url %}
|
||||
{ "file_data": { "mime_type": {{ tojson(b.media_type) }}, "file_uri": {{ tojson(b.data) }} } },
|
||||
{% else %}
|
||||
{ "inline_data": { "mime_type": {{ tojson(b.media_type) }}, "data": {{ tojson(b.data) }} } },
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{ "text": "" },
|
||||
{% endif %}
|
||||
16
sources/agents/partials/ollama_messages.jinja
Normal file
16
sources/agents/partials/ollama_messages.jinja
Normal file
@@ -0,0 +1,16 @@
|
||||
{% if existsIn(ctx, "system_prompt") %}
|
||||
{ "role": "system", "content": {{ tojson(ctx.system_prompt) }} },
|
||||
{% endif %}
|
||||
{% for msg in ctx.history %}
|
||||
{
|
||||
"role": {{ tojson(msg.role) }},
|
||||
"content": {{ tojson(msg.content) }}
|
||||
{% if existsIn(msg, "images") %}
|
||||
, "images": [
|
||||
{% for img in msg.images %}
|
||||
{{ tojson(img.data) }},
|
||||
{% endfor %}
|
||||
]
|
||||
{% endif %}
|
||||
},
|
||||
{% endfor %}
|
||||
19
sources/agents/partials/openai_assistant.jinja
Normal file
19
sources/agents/partials/openai_assistant.jinja
Normal file
@@ -0,0 +1,19 @@
|
||||
{% set tcalls = filter_by_type(msg.content_blocks, "tool_use") %}
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": {{ tojson(msg.content) }}
|
||||
{% if length(tcalls) > 0 %}
|
||||
, "tool_calls": [
|
||||
{% for b in tcalls %}
|
||||
{
|
||||
"id": {{ tojson(b.id) }},
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": {{ tojson(b.name) }},
|
||||
"arguments": {{ tojson(tojson(b.input)) }}
|
||||
}
|
||||
},
|
||||
{% endfor %}
|
||||
]
|
||||
{% endif %}
|
||||
},
|
||||
11
sources/agents/partials/openai_image_content.jinja
Normal file
11
sources/agents/partials/openai_image_content.jinja
Normal file
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{ "type": "text", "text": {{ tojson(msg.content) }} }
|
||||
{% for img in msg.images %}
|
||||
,
|
||||
{% if img.is_url %}
|
||||
{ "type": "image_url", "image_url": { "url": {{ tojson(img.data) }} } }
|
||||
{% else %}
|
||||
{ "type": "image_url", "image_url": { "url": "data:{{ img.media_type }};base64,{{ img.data }}" } }
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
]
|
||||
9
sources/agents/partials/openai_messages.jinja
Normal file
9
sources/agents/partials/openai_messages.jinja
Normal file
@@ -0,0 +1,9 @@
|
||||
{% if existsIn(ctx, "system_prompt") %}
|
||||
{ "role": "system", "content": {{ tojson(ctx.system_prompt) }} },
|
||||
{% endif %}
|
||||
{% for msg in ctx.history %}
|
||||
{% if msg.role == "assistant" %}{% include "partials/openai_assistant.jinja" %}
|
||||
{% else if length(filter_by_type(msg.content_blocks, "tool_result")) > 0 %}{% include "partials/openai_tool_results.jinja" %}
|
||||
{% else %}{% include "partials/openai_user.jinja" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
30
sources/agents/partials/openai_responses_input.jinja
Normal file
30
sources/agents/partials/openai_responses_input.jinja
Normal file
@@ -0,0 +1,30 @@
|
||||
{% for msg in ctx.history %}
|
||||
{% if msg.role == "assistant" %}
|
||||
{% if msg.content != "" %}
|
||||
{ "role": "assistant", "content": {{ tojson(msg.content) }} },
|
||||
{% endif %}
|
||||
{% for b in filter_by_type(msg.content_blocks, "tool_use") %}
|
||||
{ "type": "function_call", "call_id": {{ tojson(b.id) }}, "name": {{ tojson(b.name) }}, "arguments": {{ tojson(tojson(b.input)) }} },
|
||||
{% endfor %}
|
||||
{% else if length(filter_by_type(msg.content_blocks, "tool_result")) > 0 %}
|
||||
{% for b in filter_by_type(msg.content_blocks, "tool_result") %}
|
||||
{ "type": "function_call_output", "call_id": {{ tojson(b.tool_use_id) }}, "output": {{ tojson(b.content) }} },
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% if existsIn(msg, "images") %}
|
||||
{ "role": "user", "content": [
|
||||
{ "type": "input_text", "text": {{ tojson(msg.content) }} }
|
||||
{% for img in msg.images %}
|
||||
,
|
||||
{% if img.is_url %}
|
||||
{ "type": "input_image", "detail": "auto", "image_url": {{ tojson(img.data) }} }
|
||||
{% else %}
|
||||
{ "type": "input_image", "detail": "auto", "image_url": "data:{{ img.media_type }};base64,{{ img.data }}" }
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
] },
|
||||
{% else %}
|
||||
{ "role": "user", "content": {{ tojson(msg.content) }} },
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
3
sources/agents/partials/openai_tool_results.jinja
Normal file
3
sources/agents/partials/openai_tool_results.jinja
Normal file
@@ -0,0 +1,3 @@
|
||||
{% for b in filter_by_type(msg.content_blocks, "tool_result") %}
|
||||
{ "role": "tool", "tool_call_id": {{ tojson(b.tool_use_id) }}, "content": {{ tojson(b.content) }} },
|
||||
{% endfor %}
|
||||
5
sources/agents/partials/openai_user.jinja
Normal file
5
sources/agents/partials/openai_user.jinja
Normal file
@@ -0,0 +1,5 @@
|
||||
{% if existsIn(msg, "images") %}
|
||||
{ "role": "user", "content": {% include "partials/openai_image_content.jinja" %} },
|
||||
{% else %}
|
||||
{ "role": "user", "content": {{ tojson(msg.content) }} },
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user