Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/lib/helpers/types/agentTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* @property {string?} [uid]
* @property {string} name
* @property {string} content
* @property {string?} [response_format]
* @property {AgentTemplateConfig?} [llm_config]
*/

Expand All @@ -20,17 +19,19 @@
* @property {number} max_recursion_depth
* @property {number?} [max_output_tokens]
* @property {string?} [reasoning_effort_level]
* @property {string?} [response_format]
* @property {any} [image_composition]
* @property {any} [audio_transcription]
* @property {any} [realtime]
*/

/**
* @typedef {Object} AgentTemplateConfig
* @property {string?} provider
* @property {string?} provider
* @property {string?} model
* @property {number?} [max_output_tokens]
* @property {string?} [reasoning_effort_level]
* @property {string?} [response_format]
*/


Expand Down
2 changes: 2 additions & 0 deletions src/lib/styles/pages/_agent.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2717,6 +2717,8 @@

.tplc-input {
width: 100%;
height: 2.5rem;
box-sizing: border-box;
padding: 0.3125rem 0.5rem;
font-size: 0.75rem;
line-height: 1.4;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { slide } from 'svelte/transition';
import Select from '$lib/common/dropdowns/Select.svelte';
import { INTEGER_REGEX } from '$lib/helpers/constants';
import { LlmModelCapability, LlmModelType, ReasoningEffortLevel } from '$lib/helpers/enums';
import { LlmModelCapability, LlmModelType, ReasoningEffortLevel, ResponseFormat } from '$lib/helpers/enums';

/**
* @type {{
Expand All @@ -24,7 +24,8 @@
provider: config.provider || null,
model: config.model || null,
max_output_tokens: Number(config.max_output_tokens) > 0 ? Number(config.max_output_tokens) : null,
reasoning_effort_level: reasoningEffort
reasoning_effort_level: reasoningEffort,
response_format: config.response_format || null
};
}

Expand All @@ -39,6 +40,14 @@
}))
];

const responseFormatOptions = [
{ value: '', label: '' },
...Object.values(ResponseFormat).map(v => ({
value: v,
label: v
}))
];

/** @type {boolean} */
let collapsed = $state(false);

Expand Down Expand Up @@ -139,6 +148,13 @@
handleAgentChange();
}

/** @param {any} e */
function changeResponseFormat(e) {
const values = e?.detail?.selecteds?.map((/** @type {any} */ x) => x.value) || [];
config.response_format = values[0] || null;
handleAgentChange();
}

/** @param {any} e */
function validateIntegerInput(e) {
const reg = new RegExp(INTEGER_REGEX, 'g');
Expand Down Expand Up @@ -277,6 +293,22 @@
</div>
</div>
{/if}

<div class="cc-field">
<label for="chat-response-format" class="cc-label">
Response format
</label>
<div class="cc-input-wrap">
<Select
tag={'chat-response-format'}
containerStyles={'width: 100%;'}
placeholder={'Select a format'}
selectedValues={config.response_format ? [config.response_format] : []}
options={responseFormatOptions.filter(o => !!o.value)}
onselect={e => changeResponseFormat(e)}
/>
</div>
</div>
</div>
{/if}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@
/** @param {any} e */
function changeResponseFormat(e) {
const value = e?.detail?.selecteds?.map((/** @type {any} */ x) => x.value)[0] || null;
template.response_format = value;
if (!template.llm_config) {
template.llm_config = { provider: null, model: null };
}
template.llm_config.response_format = value;
handleAgentChange();
Comment on lines 91 to 97

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Template config shadows agent 🐞 Bug ≡ Correctness

changeResponseFormat() now creates template.llm_config = { provider: null, model: null } just to
store response_format, making template.llm_config truthy even when the template should otherwise
inherit agent settings. Downstream, InstructionAgent prefers selectedTemplate.llm_config over
selectedAgent.llm_config, which can clear provider/model and break LLM selection for that
template.
Agent Prompt
## Issue description
Setting a template response format creates a non-null `template.llm_config` with `provider/model = null`, and other screens treat `template.llm_config` as a complete override (not a partial overlay). This causes agent-level provider/model to be lost when selecting that template.

## Issue Context
- `InstructionAgent` currently computes `llmConfig` via `selectedTemplate?.llm_config || selectedAgent?.llm_config`, so any non-null template config wins, even if it only contains `response_format`.

## Fix Focus Areas
- src/routes/page/agent/[agentId]/agent-components/templates/agent-template-config.svelte[91-97]
- src/routes/page/instruction/instruction-components/instruction-agent.svelte[37-69]

## Recommended fix
Pick one of these (prefer 1 or 2):
1) **Treat template.llm_config as a partial override** in `InstructionAgent` by merging:
   - Start from `selectedAgent.llm_config`
   - Overlay only non-null/non-undefined fields from `selectedTemplate.llm_config`
   - Ensure `provider/model` fall back to agent values when template values are null
2) **Don’t instantiate `template.llm_config` when only response_format is set**, unless the rest of the app supports partial-template configs everywhere. (E.g., store template response format separately, or only set `template.llm_config` when provider/model/max tokens/etc are configured.)
3) Add an explicit “inherit agent llm_config” behavior for templates, and ensure `response_format` can override without forcing provider/model overrides.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

}

Expand Down Expand Up @@ -178,23 +181,6 @@
</script>

<div class="tplc-content">
<div class="tplc-section">
<h6 class="tplc-section-title">Template Configuration</h6>
<div class="tplc-field">
<label for="tpl-response-format" class="tplc-label">Response format</label>
<Select
tag={'tpl-response-format'}
containerStyles={'width: 100%;'}
placeholder={'Select a format'}
selectedValues={template.response_format ? [template.response_format] : []}
options={responseFormatOptions.filter(o => !!o.value)}
onselect={e => changeResponseFormat(e)}
/>
</div>
</div>

<hr class="tplc-divider" />

<div class="tplc-section">
<h6 class="tplc-section-title">LLM Configuration</h6>
<div class="tplc-field">
Expand Down Expand Up @@ -247,6 +233,18 @@
/>
</div>
{/if}

<div class="tplc-field">
<label for="tpl-response-format" class="tplc-label">Response format</label>
<Select
tag={'tpl-response-format'}
containerStyles={'width: 100%;'}
placeholder={'Select a format'}
selectedValues={template.llm_config?.response_format ? [template.llm_config.response_format] : []}
options={responseFormatOptions.filter(o => !!o.value)}
onselect={e => changeResponseFormat(e)}
/>
</div>
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
return {
name: x.name.trim().toLowerCase(),
content: x.content,
response_format: x.response_format || null,
llm_config: llmConfig
};
});
Expand Down Expand Up @@ -78,7 +77,6 @@
uid: uuidv4(),
name: x.name,
content: x.content,
response_format: x.response_format || null,
llm_config: x.llm_config || null
})) || []
];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
import Select from '$lib/common/dropdowns/Select.svelte';
import { INTEGER_REGEX } from '$lib/helpers/constants';
import { ReasoningEffortLevel } from '$lib/helpers/enums';
import { ReasoningEffortLevel, ResponseFormat } from '$lib/helpers/enums';

/**
* @type {{
Expand All @@ -11,7 +11,8 @@
* selectedModel?: string | null,
* selectedReasoningEffortLevel?: string | null,
* selectedMaxOutputTokens?: number | null,
* onSelectLlm?: (detail: { provider: import('$commonTypes').LlmConfig | null, model: string | null, reasoning_effort_level: string | null, max_output_tokens: number | null }) => void
* selectedResponseFormat?: string | null,
* onSelectLlm?: (detail: { provider: import('$commonTypes').LlmConfig | null, model: string | null, reasoning_effort_level: string | null, max_output_tokens: number | null, response_format: string | null }) => void
* }}
*/
let {
Expand All @@ -21,6 +22,7 @@
selectedModel = $bindable(null),
selectedReasoningEffortLevel = $bindable(null),
selectedMaxOutputTokens = $bindable(null),
selectedResponseFormat = $bindable(null),
onSelectLlm
} = $props();

Expand All @@ -30,6 +32,12 @@
label: v
}));

/** @type {import('$commonTypes').LabelValuePair[]} */
const responseFormatOptions = Object.values(ResponseFormat).map(v => ({
value: v,
label: v
}));

/** @type {import('$commonTypes').LabelValuePair[]} */
let providerOptions = $derived(
llmConfigs?.map(x => ({
Expand Down Expand Up @@ -99,6 +107,14 @@
fireSelectLlm();
}

/** @param {any} e */
function selectResponseFormat(e) {
// @ts-ignore
const selectedValues = e.detail.selecteds?.map(x => x.value) || [];
selectedResponseFormat = selectedValues.length > 0 ? selectedValues[0] : null;
fireSelectLlm();
}

/** @param {any} e */
function validateIntegerInput(e) {
const reg = new RegExp(INTEGER_REGEX, 'g');
Expand All @@ -112,7 +128,8 @@
provider: selectedProvider || null,
model: selectedModel,
reasoning_effort_level: selectedReasoningEffortLevel || null,
max_output_tokens: selectedMaxOutputTokens || null
max_output_tokens: selectedMaxOutputTokens || null,
response_format: selectedResponseFormat || null
});
}
</script>
Expand Down Expand Up @@ -183,4 +200,19 @@
/>
</div>
{/if}

<div>
<label for="response-format-select" class="mb-1.5 inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-primary">
<i class="mdi mdi-code-json text-sm leading-none"></i>
Response format
</label>
<Select
tag={'response-format-select'}
placeholder={'Select a format'}
disabled={disabled}
selectedValues={selectedResponseFormat ? [selectedResponseFormat] : []}
options={responseFormatOptions}
onselect={e => selectResponseFormat(e)}
/>
</div>
</div>
11 changes: 10 additions & 1 deletion src/routes/page/instruction/testing/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
/** @type {number | null} */
let selectedMaxOutputTokens = $state(null);

/** @type {string | null} */
let selectedResponseFormat = $state(null);

/** @type {string | null} */
let selectedTemplate = $state(null);

Expand Down Expand Up @@ -114,6 +117,9 @@
if (selectedMaxOutputTokens && selectedMaxOutputTokens > 0) {
clonedStates.push({ key: 'max_tokens', value: selectedMaxOutputTokens.toString() });
}
if (selectedResponseFormat) {
clonedStates.push({ key: 'response_format', value: selectedResponseFormat });
}

const formattedStates = formatKeyValues(states, clonedStates);
const formatedArgs = formatKeyValues(args);
Expand Down Expand Up @@ -194,6 +200,7 @@
selectedModel = modelName;
selectedReasoningEffortLevel = llmConfig?.reasoning_effort_level || null;
selectedMaxOutputTokens = llmConfig?.max_output_tokens || null;
selectedResponseFormat = llmConfig?.response_format || null;

if (selectedAgent?.id) {
initAgentCodeScripts(selectedAgent.id);
Expand All @@ -202,12 +209,13 @@
}
}

/** @param {{ provider: import('$commonTypes').LlmConfig | null, model: string | null, reasoning_effort_level: string | null, max_output_tokens: number | null }} detail */
/** @param {{ provider: import('$commonTypes').LlmConfig | null, model: string | null, reasoning_effort_level: string | null, max_output_tokens: number | null, response_format: string | null }} detail */
function onLlmSelected(detail) {
selectedProvider = detail.provider || null;
selectedModel = detail.model || '';
selectedReasoningEffortLevel = detail.reasoning_effort_level || null;
selectedMaxOutputTokens = detail.max_output_tokens || null;
selectedResponseFormat = detail.response_format || null;
}

/** @param {string} agentId */
Expand Down Expand Up @@ -404,6 +412,7 @@
bind:selectedModel={selectedModel}
bind:selectedReasoningEffortLevel={selectedReasoningEffortLevel}
bind:selectedMaxOutputTokens={selectedMaxOutputTokens}
bind:selectedResponseFormat={selectedResponseFormat}
onSelectLlm={detail => onLlmSelected(detail)}
/>
</div>
Expand Down
Loading