@ai-matrx/agents 0.59.233 → 0.59.234
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -3
- package/dist/settings/index.cjs +4 -0
- package/dist/settings/index.d.cts +8 -1
- package/dist/settings/index.d.ts +8 -1
- package/dist/settings/index.js +4 -0
- package/dist/settings/react/index.cjs +189 -67
- package/dist/settings/react/index.d.cts +7 -73
- package/dist/settings/react/index.d.ts +7 -73
- package/dist/settings/react/index.js +188 -66
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.59.
|
|
3
|
+
## 0.59.234
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/matrx-agents/src`.
|
|
5
|
+
- **The Voice row is the panel's own (owner, 2026-10-21: one settings experience).** `ModelSettingsPanel` draws `tts_voice` with `VoiceSettingControl` — one voice, or named speakers (name · voice · remove, "Add speaker", the model's `multi_speaker.max`) when the model declares `multi_speaker` — in every host, so the chat's "Model and overrides" edits voices exactly as the builder does. `SettingsWriteTarget.changeMany` (optional) writes `tts_voice` + `multi_speaker` as one change; without it the panel calls `change` per key. New `settingControl(controls, key)` in `./settings`. Removed: the panel's `renderRow` prop and the `SettingRowFrame` / `SettingRowLabel` / `formatSettingValue` exports of `./settings/react` (their one consumer, the builder's hand-drawn voice row, is gone). Guard: `settings/react/model-settings-panel.test.tsx`. Consumer action: drop `renderRow` and any `SettingRowFrame` / `SettingRowLabel` import; give a target that writes a record `changeMany`.
|
|
7
6
|
|
|
8
7
|
## 0.59.231
|
|
9
8
|
|
package/dist/settings/index.cjs
CHANGED
|
@@ -57,6 +57,7 @@ __export(settings_exports, {
|
|
|
57
57
|
readSettingsEntry: () => readSettingsEntry,
|
|
58
58
|
resolveConflicts: () => resolveConflicts,
|
|
59
59
|
sanitizeSettings: () => sanitizeSettings,
|
|
60
|
+
settingControl: () => settingControl,
|
|
60
61
|
settingLabel: () => settingLabel,
|
|
61
62
|
settingStateOf: () => settingStateOf,
|
|
62
63
|
startingValueFor: () => startingValueFor,
|
|
@@ -289,6 +290,9 @@ var CATCHALL_EXCLUDED = /* @__PURE__ */ new Set([
|
|
|
289
290
|
// model now declares `tools` for the tool-support capability).
|
|
290
291
|
...UI_GATE_KEYS
|
|
291
292
|
]);
|
|
293
|
+
function settingControl(controls, key) {
|
|
294
|
+
return lookupControl(controls, key);
|
|
295
|
+
}
|
|
292
296
|
function lookupControl(controls, key) {
|
|
293
297
|
if (!controls) return null;
|
|
294
298
|
if (CATCHALL_EXCLUDED.has(key)) {
|
|
@@ -229,6 +229,8 @@ interface RenderGroup {
|
|
|
229
229
|
* NormalizedControls variant in the codebase (both are a key→ControlDefinition
|
|
230
230
|
* map plus rawControls/unmappedControls). */
|
|
231
231
|
type ControlsLike = Record<string, unknown> | null | undefined;
|
|
232
|
+
/** The model's control for one setting key (`null` when the model declares none). */
|
|
233
|
+
declare function settingControl(controls: ControlsLike, key: string): ControlDefinition | null;
|
|
232
234
|
/**
|
|
233
235
|
* Build the STANDARD settings list for the selected model.
|
|
234
236
|
*
|
|
@@ -654,6 +656,11 @@ interface SettingsWriteTarget {
|
|
|
654
656
|
read(key: string, control: ControlDefinition | null): SettingRowRead;
|
|
655
657
|
/** The person edited the control. */
|
|
656
658
|
change(key: string, value: unknown, control: ControlDefinition | null): void;
|
|
659
|
+
/**
|
|
660
|
+
* Several settings that are one choice, written together (the Voice row's `tts_voice` +
|
|
661
|
+
* `multi_speaker`). Without it the panel calls `change` once per key.
|
|
662
|
+
*/
|
|
663
|
+
changeMany?(changes: Record<string, unknown>): void;
|
|
657
664
|
/** The person ticked an unset row (store `startingValueFor`). */
|
|
658
665
|
turnOn(key: string, control: ControlDefinition): void;
|
|
659
666
|
/** The person cleared the row back to "not set". */
|
|
@@ -721,4 +728,4 @@ interface CapabilitiesWriteTarget {
|
|
|
721
728
|
error?: string | null;
|
|
722
729
|
}
|
|
723
730
|
|
|
724
|
-
export { AUTO_MEANS_UNSET_KEYS, AUTO_VALUE, type AgentContext, type AgentSettings, type AgentSettingsEntry, type AgentSettingsState, type AgentSource, type AgentVariable, CATALOGUE_KEYS, type CapabilitiesWriteTarget, type CatalogueEntry, type CatalogueGroup, type ConflictAction, type ConflictItem, type ConflictReason, type ConflictSummary, type ControlDefinition, type ControlType, EMPTY_UI_GATES, ENUM_OFF_VALUE, type ExtraSettingKeys, type InitializeSettingsInput, type LLMParams, type ModelRowTarget, type NormalizedControls, PARAM_ALIASES, type PendingModelSwitch, type RenderGroup, type ResolutionMode, SETTINGS_CATALOGUE, type SettingRowFacts, type SettingRowRead, type SettingRowView, type SettingState, type SettingsGroupId, type SettingsModelInfo, type SettingsRow, type SettingsStore, type SettingsStoreConfig, type SettingsWriteTarget, UI_GATE_EDITABLE_KEYS, UI_GATE_KEYS, type UiGateEditableKey, type UiGateKey, type UiGates, type VariableCustomComponentRef, buildApiPayload, buildSettingsRows, computeOverrideDiff, createSettingsStore, detectConflicts, effectiveOfferingPinOf, extraSettingKeys, extractModelDefaults, gateEnabled, getActionForMode, isOffValue, isUiGateKey, isUnsetChoice, mergeEffectiveSettings, mergeVariableValues, offValueFor, parseModelControls, parseUiGates, readApiPayload, readConflictActions, readConflictSummary, readEffectiveModelId, readEffectiveSettings, readEffectiveVariableValues, readPreviewedResolution, readSettingsEntry, resolveConflicts, sanitizeSettings, settingLabel, settingStateOf, startingValueFor, withSettingState };
|
|
731
|
+
export { AUTO_MEANS_UNSET_KEYS, AUTO_VALUE, type AgentContext, type AgentSettings, type AgentSettingsEntry, type AgentSettingsState, type AgentSource, type AgentVariable, CATALOGUE_KEYS, type CapabilitiesWriteTarget, type CatalogueEntry, type CatalogueGroup, type ConflictAction, type ConflictItem, type ConflictReason, type ConflictSummary, type ControlDefinition, type ControlType, EMPTY_UI_GATES, ENUM_OFF_VALUE, type ExtraSettingKeys, type InitializeSettingsInput, type LLMParams, type ModelRowTarget, type NormalizedControls, PARAM_ALIASES, type PendingModelSwitch, type RenderGroup, type ResolutionMode, SETTINGS_CATALOGUE, type SettingRowFacts, type SettingRowRead, type SettingRowView, type SettingState, type SettingsGroupId, type SettingsModelInfo, type SettingsRow, type SettingsStore, type SettingsStoreConfig, type SettingsWriteTarget, UI_GATE_EDITABLE_KEYS, UI_GATE_KEYS, type UiGateEditableKey, type UiGateKey, type UiGates, type VariableCustomComponentRef, buildApiPayload, buildSettingsRows, computeOverrideDiff, createSettingsStore, detectConflicts, effectiveOfferingPinOf, extraSettingKeys, extractModelDefaults, gateEnabled, getActionForMode, isOffValue, isUiGateKey, isUnsetChoice, mergeEffectiveSettings, mergeVariableValues, offValueFor, parseModelControls, parseUiGates, readApiPayload, readConflictActions, readConflictSummary, readEffectiveModelId, readEffectiveSettings, readEffectiveVariableValues, readPreviewedResolution, readSettingsEntry, resolveConflicts, sanitizeSettings, settingControl, settingLabel, settingStateOf, startingValueFor, withSettingState };
|
package/dist/settings/index.d.ts
CHANGED
|
@@ -229,6 +229,8 @@ interface RenderGroup {
|
|
|
229
229
|
* NormalizedControls variant in the codebase (both are a key→ControlDefinition
|
|
230
230
|
* map plus rawControls/unmappedControls). */
|
|
231
231
|
type ControlsLike = Record<string, unknown> | null | undefined;
|
|
232
|
+
/** The model's control for one setting key (`null` when the model declares none). */
|
|
233
|
+
declare function settingControl(controls: ControlsLike, key: string): ControlDefinition | null;
|
|
232
234
|
/**
|
|
233
235
|
* Build the STANDARD settings list for the selected model.
|
|
234
236
|
*
|
|
@@ -654,6 +656,11 @@ interface SettingsWriteTarget {
|
|
|
654
656
|
read(key: string, control: ControlDefinition | null): SettingRowRead;
|
|
655
657
|
/** The person edited the control. */
|
|
656
658
|
change(key: string, value: unknown, control: ControlDefinition | null): void;
|
|
659
|
+
/**
|
|
660
|
+
* Several settings that are one choice, written together (the Voice row's `tts_voice` +
|
|
661
|
+
* `multi_speaker`). Without it the panel calls `change` once per key.
|
|
662
|
+
*/
|
|
663
|
+
changeMany?(changes: Record<string, unknown>): void;
|
|
657
664
|
/** The person ticked an unset row (store `startingValueFor`). */
|
|
658
665
|
turnOn(key: string, control: ControlDefinition): void;
|
|
659
666
|
/** The person cleared the row back to "not set". */
|
|
@@ -721,4 +728,4 @@ interface CapabilitiesWriteTarget {
|
|
|
721
728
|
error?: string | null;
|
|
722
729
|
}
|
|
723
730
|
|
|
724
|
-
export { AUTO_MEANS_UNSET_KEYS, AUTO_VALUE, type AgentContext, type AgentSettings, type AgentSettingsEntry, type AgentSettingsState, type AgentSource, type AgentVariable, CATALOGUE_KEYS, type CapabilitiesWriteTarget, type CatalogueEntry, type CatalogueGroup, type ConflictAction, type ConflictItem, type ConflictReason, type ConflictSummary, type ControlDefinition, type ControlType, EMPTY_UI_GATES, ENUM_OFF_VALUE, type ExtraSettingKeys, type InitializeSettingsInput, type LLMParams, type ModelRowTarget, type NormalizedControls, PARAM_ALIASES, type PendingModelSwitch, type RenderGroup, type ResolutionMode, SETTINGS_CATALOGUE, type SettingRowFacts, type SettingRowRead, type SettingRowView, type SettingState, type SettingsGroupId, type SettingsModelInfo, type SettingsRow, type SettingsStore, type SettingsStoreConfig, type SettingsWriteTarget, UI_GATE_EDITABLE_KEYS, UI_GATE_KEYS, type UiGateEditableKey, type UiGateKey, type UiGates, type VariableCustomComponentRef, buildApiPayload, buildSettingsRows, computeOverrideDiff, createSettingsStore, detectConflicts, effectiveOfferingPinOf, extraSettingKeys, extractModelDefaults, gateEnabled, getActionForMode, isOffValue, isUiGateKey, isUnsetChoice, mergeEffectiveSettings, mergeVariableValues, offValueFor, parseModelControls, parseUiGates, readApiPayload, readConflictActions, readConflictSummary, readEffectiveModelId, readEffectiveSettings, readEffectiveVariableValues, readPreviewedResolution, readSettingsEntry, resolveConflicts, sanitizeSettings, settingLabel, settingStateOf, startingValueFor, withSettingState };
|
|
731
|
+
export { AUTO_MEANS_UNSET_KEYS, AUTO_VALUE, type AgentContext, type AgentSettings, type AgentSettingsEntry, type AgentSettingsState, type AgentSource, type AgentVariable, CATALOGUE_KEYS, type CapabilitiesWriteTarget, type CatalogueEntry, type CatalogueGroup, type ConflictAction, type ConflictItem, type ConflictReason, type ConflictSummary, type ControlDefinition, type ControlType, EMPTY_UI_GATES, ENUM_OFF_VALUE, type ExtraSettingKeys, type InitializeSettingsInput, type LLMParams, type ModelRowTarget, type NormalizedControls, PARAM_ALIASES, type PendingModelSwitch, type RenderGroup, type ResolutionMode, SETTINGS_CATALOGUE, type SettingRowFacts, type SettingRowRead, type SettingRowView, type SettingState, type SettingsGroupId, type SettingsModelInfo, type SettingsRow, type SettingsStore, type SettingsStoreConfig, type SettingsWriteTarget, UI_GATE_EDITABLE_KEYS, UI_GATE_KEYS, type UiGateEditableKey, type UiGateKey, type UiGates, type VariableCustomComponentRef, buildApiPayload, buildSettingsRows, computeOverrideDiff, createSettingsStore, detectConflicts, effectiveOfferingPinOf, extraSettingKeys, extractModelDefaults, gateEnabled, getActionForMode, isOffValue, isUiGateKey, isUnsetChoice, mergeEffectiveSettings, mergeVariableValues, offValueFor, parseModelControls, parseUiGates, readApiPayload, readConflictActions, readConflictSummary, readEffectiveModelId, readEffectiveSettings, readEffectiveVariableValues, readPreviewedResolution, readSettingsEntry, resolveConflicts, sanitizeSettings, settingControl, settingLabel, settingStateOf, startingValueFor, withSettingState };
|
package/dist/settings/index.js
CHANGED
|
@@ -223,6 +223,9 @@ var CATCHALL_EXCLUDED = /* @__PURE__ */ new Set([
|
|
|
223
223
|
// model now declares `tools` for the tool-support capability).
|
|
224
224
|
...UI_GATE_KEYS
|
|
225
225
|
]);
|
|
226
|
+
function settingControl(controls, key) {
|
|
227
|
+
return lookupControl(controls, key);
|
|
228
|
+
}
|
|
226
229
|
function lookupControl(controls, key) {
|
|
227
230
|
if (!controls) return null;
|
|
228
231
|
if (CATCHALL_EXCLUDED.has(key)) {
|
|
@@ -1032,6 +1035,7 @@ export {
|
|
|
1032
1035
|
readSettingsEntry,
|
|
1033
1036
|
resolveConflicts,
|
|
1034
1037
|
sanitizeSettings,
|
|
1038
|
+
settingControl,
|
|
1035
1039
|
settingLabel,
|
|
1036
1040
|
settingStateOf,
|
|
1037
1041
|
startingValueFor,
|
|
@@ -23,9 +23,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
23
23
|
var react_exports = {};
|
|
24
24
|
__export(react_exports, {
|
|
25
25
|
ModelSettingsPanel: () => ModelSettingsPanel,
|
|
26
|
-
SettingRowFrame: () => SettingRowFrame,
|
|
27
|
-
SettingRowLabel: () => RowLabel,
|
|
28
|
-
formatSettingValue: () => formatSettingValue,
|
|
29
26
|
useEffectiveSettings: () => useEffectiveSettings,
|
|
30
27
|
useSettingsEntry: () => useSettingsEntry,
|
|
31
28
|
useSettingsSelector: () => useSettingsSelector
|
|
@@ -210,7 +207,7 @@ function readEffectiveSettings(entry) {
|
|
|
210
207
|
|
|
211
208
|
// settings/react/ModelSettingsPanel.tsx
|
|
212
209
|
var import_design_system4 = require("@ai-matrx/design-system");
|
|
213
|
-
var
|
|
210
|
+
var import_controls4 = require("@ai-matrx/design-system/controls");
|
|
214
211
|
var import_react2 = require("@ai-matrx/agents/models/react");
|
|
215
212
|
|
|
216
213
|
// settings/settings-catalogue.ts
|
|
@@ -326,6 +323,9 @@ var CATCHALL_EXCLUDED = /* @__PURE__ */ new Set([
|
|
|
326
323
|
// model now declares `tools` for the tool-support capability).
|
|
327
324
|
...UI_GATE_KEYS
|
|
328
325
|
]);
|
|
326
|
+
function settingControl(controls, key) {
|
|
327
|
+
return lookupControl(controls, key);
|
|
328
|
+
}
|
|
329
329
|
function lookupControl(controls, key) {
|
|
330
330
|
if (!controls) return null;
|
|
331
331
|
if (CATCHALL_EXCLUDED.has(key)) {
|
|
@@ -868,29 +868,142 @@ function NumberInput({
|
|
|
868
868
|
);
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
-
// settings/react/
|
|
871
|
+
// settings/react/VoiceSettingControl.tsx
|
|
872
|
+
var import_controls3 = require("@ai-matrx/design-system/controls");
|
|
873
|
+
var import_icons2 = require("@ai-matrx/design-system/icons");
|
|
872
874
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
875
|
+
function speakersOf(value, voices) {
|
|
876
|
+
if (!Array.isArray(value)) return [];
|
|
877
|
+
return value.map((entry, index) => {
|
|
878
|
+
const record = entry !== null && typeof entry === "object" ? entry : {};
|
|
879
|
+
return {
|
|
880
|
+
name: typeof record.name === "string" ? record.name : `Speaker ${index + 1}`,
|
|
881
|
+
voice: typeof record.voice === "string" ? record.voice : voices[0] ?? ""
|
|
882
|
+
};
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
function VoiceSettingControl({ voices, value, multiSpeaker, onChange, idPrefix, disabled = false }) {
|
|
886
|
+
const isMulti = Array.isArray(value);
|
|
887
|
+
const speakers = speakersOf(value, voices);
|
|
888
|
+
const single = typeof value === "string" && value ? value : voices[0] ?? "";
|
|
889
|
+
const max = multiSpeaker?.max !== void 0 && multiSpeaker.max > 0 ? multiSpeaker.max : void 0;
|
|
890
|
+
const canAdd = max === void 0 || speakers.length < max;
|
|
891
|
+
const options = voices.map((voice) => ({ value: voice, label: voice }));
|
|
892
|
+
const voiceSelect = (current, label, pick) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
893
|
+
import_controls3.Select,
|
|
894
|
+
{
|
|
895
|
+
value: current,
|
|
896
|
+
options: options.some((o) => o.value === current) ? options : [{ value: current, label: current }, ...options],
|
|
897
|
+
onValueChange: pick,
|
|
898
|
+
"aria-label": label,
|
|
899
|
+
disabled,
|
|
900
|
+
className: "min-w-0"
|
|
901
|
+
}
|
|
902
|
+
);
|
|
903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex min-w-0 flex-col gap-1", "data-voice-control": "", children: [
|
|
904
|
+
multiSpeaker || isMulti ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
905
|
+
import_controls3.SegmentedControl,
|
|
906
|
+
{
|
|
907
|
+
"aria-label": "Voices",
|
|
908
|
+
value: isMulti ? "multi" : "single",
|
|
909
|
+
onValueChange: (next) => {
|
|
910
|
+
if (next === "multi" && !isMulti) {
|
|
911
|
+
onChange(
|
|
912
|
+
[
|
|
913
|
+
{ name: "Speaker 1", voice: single },
|
|
914
|
+
{ name: "Speaker 2", voice: voices[1] ?? single }
|
|
915
|
+
],
|
|
916
|
+
true
|
|
917
|
+
);
|
|
918
|
+
} else if (next === "single" && isMulti) {
|
|
919
|
+
onChange(speakers[0]?.voice || voices[0] || "", false);
|
|
920
|
+
}
|
|
921
|
+
},
|
|
922
|
+
data: [
|
|
923
|
+
{ value: "single", label: "One voice", disabled },
|
|
924
|
+
{ value: "multi", label: "Speakers", disabled: disabled || !multiSpeaker }
|
|
925
|
+
]
|
|
926
|
+
}
|
|
927
|
+
) : null,
|
|
928
|
+
!isMulti ? voiceSelect(single, "Voice", (next) => onChange(next, false)) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
929
|
+
speakers.map((speaker, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex min-w-0 items-center gap-1", "data-speaker": index, children: [
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
931
|
+
import_controls3.Field,
|
|
932
|
+
{
|
|
933
|
+
id: `${idPrefix}-speaker-${index}`,
|
|
934
|
+
"aria-label": `Speaker ${index + 1} name`,
|
|
935
|
+
value: speaker.name,
|
|
936
|
+
onChange: (event) => onChange(
|
|
937
|
+
speakers.map((s, i) => i === index ? { ...s, name: event.target.value } : s),
|
|
938
|
+
true
|
|
939
|
+
),
|
|
940
|
+
disabled,
|
|
941
|
+
className: "min-w-0 flex-1"
|
|
942
|
+
}
|
|
943
|
+
),
|
|
944
|
+
voiceSelect(
|
|
945
|
+
speaker.voice,
|
|
946
|
+
`Speaker ${index + 1} voice`,
|
|
947
|
+
(next) => onChange(
|
|
948
|
+
speakers.map((s, i) => i === index ? { ...s, voice: next } : s),
|
|
949
|
+
true
|
|
950
|
+
)
|
|
951
|
+
),
|
|
952
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
953
|
+
import_controls3.Button,
|
|
954
|
+
{
|
|
955
|
+
variant: "quiet",
|
|
956
|
+
removes: true,
|
|
957
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.XIcon, {}),
|
|
958
|
+
onClick: () => onChange(speakers.filter((_, i) => i !== index), true),
|
|
959
|
+
disabled: disabled || speakers.length <= 2,
|
|
960
|
+
"aria-label": `Remove speaker ${index + 1}`,
|
|
961
|
+
title: "Remove speaker"
|
|
962
|
+
}
|
|
963
|
+
)
|
|
964
|
+
] }, index)),
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
966
|
+
import_controls3.Button,
|
|
967
|
+
{
|
|
968
|
+
variant: "quiet",
|
|
969
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.PlusIcon, {}),
|
|
970
|
+
onClick: () => onChange([...speakers, { name: `Speaker ${speakers.length + 1}`, voice: voices[0] ?? "" }], true),
|
|
971
|
+
disabled: disabled || !canAdd,
|
|
972
|
+
title: canAdd ? "Add a speaker" : `This model takes up to ${max} speakers`,
|
|
973
|
+
children: "Add speaker"
|
|
974
|
+
}
|
|
975
|
+
) })
|
|
976
|
+
] })
|
|
977
|
+
] });
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// settings/react/ModelSettingsPanel.tsx
|
|
981
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
873
982
|
function StatusGlyph({ issue, source }) {
|
|
874
983
|
const title = issue ? issue.message : source ? `Valid \xB7 ${source}` : "Valid";
|
|
875
|
-
return /* @__PURE__ */ (0,
|
|
984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
876
985
|
"span",
|
|
877
986
|
{
|
|
878
987
|
className: (0, import_cn.cn)("inline-flex h-7 w-6 shrink-0 items-center justify-center", issue ? "text-warning" : "text-success"),
|
|
879
988
|
role: "img",
|
|
880
989
|
"aria-label": title,
|
|
881
990
|
title,
|
|
882
|
-
children: issue ? /* @__PURE__ */ (0,
|
|
991
|
+
children: issue ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TriangleAlertGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CircleCheckGlyph, { className: "h-3.5 w-3.5" })
|
|
883
992
|
}
|
|
884
993
|
);
|
|
885
994
|
}
|
|
886
|
-
function
|
|
995
|
+
function changeTogether(target, changes, controls) {
|
|
996
|
+
if (target.changeMany) target.changeMany(changes);
|
|
997
|
+
else for (const [key, value] of Object.entries(changes)) target.change(key, value, controls[key] ?? null);
|
|
998
|
+
}
|
|
999
|
+
function ModelSettingRow({ row, control, target, idPrefix, disabled, multiSpeaker }) {
|
|
887
1000
|
const read = target.read(row.key, control);
|
|
888
1001
|
const resetLabel = target.resetLabel ?? "Reset to agent";
|
|
889
|
-
const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */ (0,
|
|
890
|
-
|
|
1002
|
+
const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1003
|
+
import_controls4.Button,
|
|
891
1004
|
{
|
|
892
1005
|
variant: "quiet",
|
|
893
|
-
icon: /* @__PURE__ */ (0,
|
|
1006
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RotateCcwGlyph, {}),
|
|
894
1007
|
onClick: () => target.resetToInherited?.(row.key),
|
|
895
1008
|
disabled,
|
|
896
1009
|
"aria-label": `${resetLabel}: ${row.label}`,
|
|
@@ -899,20 +1012,20 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
899
1012
|
}
|
|
900
1013
|
) : null;
|
|
901
1014
|
if (read.state === "bound") {
|
|
902
|
-
return /* @__PURE__ */ (0,
|
|
1015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
903
1016
|
SettingRowFrame,
|
|
904
1017
|
{
|
|
905
1018
|
rowKey: row.key,
|
|
906
1019
|
state: "bound",
|
|
907
|
-
leading: /* @__PURE__ */ (0,
|
|
908
|
-
label: /* @__PURE__ */ (0,
|
|
909
|
-
actions: /* @__PURE__ */ (0,
|
|
1020
|
+
leading: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Checkbox, { checked: true, disabled: true, "aria-label": `${row.label} is a run input` }),
|
|
1021
|
+
label: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RowLabel, { children: row.label }),
|
|
1022
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
910
1023
|
reset,
|
|
911
|
-
target.unbind ? /* @__PURE__ */ (0,
|
|
912
|
-
|
|
1024
|
+
target.unbind ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1025
|
+
import_controls4.Button,
|
|
913
1026
|
{
|
|
914
1027
|
variant: "quiet",
|
|
915
|
-
icon: /* @__PURE__ */ (0,
|
|
1028
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UnlinkGlyph, {}),
|
|
916
1029
|
onClick: () => target.unbind?.(row.key, control),
|
|
917
1030
|
disabled,
|
|
918
1031
|
"aria-label": `Make ${row.label} a fixed setting`,
|
|
@@ -920,9 +1033,9 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
920
1033
|
}
|
|
921
1034
|
) : null
|
|
922
1035
|
] }),
|
|
923
|
-
children: /* @__PURE__ */ (0,
|
|
924
|
-
/* @__PURE__ */ (0,
|
|
925
|
-
/* @__PURE__ */ (0,
|
|
1036
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex min-h-7 min-w-0 items-center gap-2", "data-bound-control": row.key, children: [
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls4.Chip, { tone: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VariableGlyph, {}), label: `{{${read.variableName}}}` }),
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate type-meta text-muted-foreground", children: read.value === void 0 || read.value === null || read.value === "" ? "Model default" : formatSettingValue(read.value) })
|
|
926
1039
|
] })
|
|
927
1040
|
}
|
|
928
1041
|
);
|
|
@@ -932,12 +1045,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
932
1045
|
const isOff = isSet && isOffValue(value, control);
|
|
933
1046
|
const checkboxId = `${idPrefix}-setting-${row.key}`;
|
|
934
1047
|
const canBind = Boolean(target.bind) && (target.canBind?.(row.key) ?? true);
|
|
935
|
-
return /* @__PURE__ */ (0,
|
|
1048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
936
1049
|
SettingRowFrame,
|
|
937
1050
|
{
|
|
938
1051
|
rowKey: row.key,
|
|
939
1052
|
state: isOff ? "off" : read.state,
|
|
940
|
-
leading: /* @__PURE__ */ (0,
|
|
1053
|
+
leading: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
941
1054
|
import_design_system4.Checkbox,
|
|
942
1055
|
{
|
|
943
1056
|
id: checkboxId,
|
|
@@ -946,14 +1059,14 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
946
1059
|
onCheckedChange: (next) => next === true ? target.turnOn(row.key, control) : target.clear(row.key)
|
|
947
1060
|
}
|
|
948
1061
|
),
|
|
949
|
-
label: /* @__PURE__ */ (0,
|
|
950
|
-
actions: /* @__PURE__ */ (0,
|
|
951
|
-
/* @__PURE__ */ (0,
|
|
952
|
-
canBind ? /* @__PURE__ */ (0,
|
|
953
|
-
|
|
1062
|
+
label: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RowLabel, { htmlFor: checkboxId, muted: !isSet, children: row.label }),
|
|
1063
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1064
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusGlyph, { issue: read.issue, source: read.source }),
|
|
1065
|
+
canBind ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1066
|
+
import_controls4.Button,
|
|
954
1067
|
{
|
|
955
1068
|
variant: "quiet",
|
|
956
|
-
icon: /* @__PURE__ */ (0,
|
|
1069
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VariableGlyph, {}),
|
|
957
1070
|
onClick: () => target.bind?.(row.key, control),
|
|
958
1071
|
disabled,
|
|
959
1072
|
"aria-label": `Make ${row.label} a run input`,
|
|
@@ -961,11 +1074,11 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
961
1074
|
"data-bind-control": row.key
|
|
962
1075
|
}
|
|
963
1076
|
) : null,
|
|
964
|
-
isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */ (0,
|
|
965
|
-
|
|
1077
|
+
isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1078
|
+
import_controls4.Button,
|
|
966
1079
|
{
|
|
967
1080
|
variant: "quiet",
|
|
968
|
-
icon: /* @__PURE__ */ (0,
|
|
1081
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WrenchGlyph, {}),
|
|
969
1082
|
onClick: () => target.fix?.(row.key),
|
|
970
1083
|
disabled,
|
|
971
1084
|
"aria-label": `Fix ${row.label} automatically`,
|
|
@@ -973,12 +1086,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
973
1086
|
}
|
|
974
1087
|
) : null,
|
|
975
1088
|
reset,
|
|
976
|
-
isSet ? /* @__PURE__ */ (0,
|
|
977
|
-
|
|
1089
|
+
isSet ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1090
|
+
import_controls4.Button,
|
|
978
1091
|
{
|
|
979
1092
|
variant: "quiet",
|
|
980
1093
|
removes: true,
|
|
981
|
-
icon: /* @__PURE__ */ (0,
|
|
1094
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Trash2Glyph, {}),
|
|
982
1095
|
onClick: () => target.clear(row.key),
|
|
983
1096
|
disabled,
|
|
984
1097
|
"aria-label": `Clear ${row.label} to not set`,
|
|
@@ -987,8 +1100,18 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
987
1100
|
}
|
|
988
1101
|
) : null
|
|
989
1102
|
] }),
|
|
990
|
-
children: isSet ? /* @__PURE__ */ (0,
|
|
991
|
-
|
|
1103
|
+
children: isSet && row.key === "tts_voice" && control.enum?.length && (multiSpeaker || Array.isArray(value)) ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1104
|
+
VoiceSettingControl,
|
|
1105
|
+
{
|
|
1106
|
+
voices: control.enum.map(String),
|
|
1107
|
+
value,
|
|
1108
|
+
multiSpeaker: multiSpeaker ? { max: multiSpeaker.max } : null,
|
|
1109
|
+
onChange: (voice, multi) => changeTogether(target, { tts_voice: voice, multi_speaker: multi }, { tts_voice: control, multi_speaker: multiSpeaker }),
|
|
1110
|
+
idPrefix: `${idPrefix}-voice`,
|
|
1111
|
+
disabled
|
|
1112
|
+
}
|
|
1113
|
+
) : isSet ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1114
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
992
1115
|
SettingControlInput,
|
|
993
1116
|
{
|
|
994
1117
|
settingKey: row.key,
|
|
@@ -999,40 +1122,40 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
999
1122
|
id: `${idPrefix}-control-${row.key}`
|
|
1000
1123
|
}
|
|
1001
1124
|
),
|
|
1002
|
-
read.issue ? /* @__PURE__ */ (0,
|
|
1003
|
-
] }) : /* @__PURE__ */ (0,
|
|
1125
|
+
read.issue ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "pt-1 type-meta text-warning-ink", children: read.issue.message }) : null
|
|
1126
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RowText, { children: read.modelDefault !== void 0 && read.modelDefault !== null ? `Not set \xB7 Model default: ${formatSettingValue(read.modelDefault)}` : "Not set" })
|
|
1004
1127
|
}
|
|
1005
1128
|
);
|
|
1006
1129
|
}
|
|
1007
1130
|
function ExtraSettingRow({ rowKey, label, value, kind, onClear, onReset, resetLabel = "Reset to agent", disabled = false }) {
|
|
1008
|
-
return /* @__PURE__ */ (0,
|
|
1131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1009
1132
|
SettingRowFrame,
|
|
1010
1133
|
{
|
|
1011
1134
|
rowKey,
|
|
1012
1135
|
state: kind,
|
|
1013
|
-
label: /* @__PURE__ */ (0,
|
|
1014
|
-
actions: /* @__PURE__ */ (0,
|
|
1015
|
-
kind === "translated" ? /* @__PURE__ */ (0,
|
|
1016
|
-
onReset ? /* @__PURE__ */ (0,
|
|
1136
|
+
label: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RowLabel, { children: label }),
|
|
1137
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1138
|
+
kind === "translated" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls4.Chip, { tone: "sky", label: "Translated", title: "Kept as set and sent as this model's closest equivalent" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls4.Chip, { tone: "warning", label: "Not on this model", title: "This model has no such setting" }),
|
|
1139
|
+
onReset ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls4.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RotateCcwGlyph, {}), onClick: onReset, disabled, "aria-label": `${resetLabel}: ${label}`, title: resetLabel, "data-setting-reset": rowKey }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls4.Button, { variant: "quiet", removes: true, icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Trash2Glyph, {}), onClick: onClear, disabled, "aria-label": `Clear ${label}`, title: "Clear to not set", "data-setting-clear": rowKey })
|
|
1017
1140
|
] }),
|
|
1018
|
-
children: /* @__PURE__ */ (0,
|
|
1141
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RowText, { mono: value !== void 0 && value !== null, children: value === void 0 || value === null ? "Not set" : isOffValue(value, null) ? "Off" : formatSettingValue(value) })
|
|
1019
1142
|
}
|
|
1020
1143
|
);
|
|
1021
1144
|
}
|
|
1022
1145
|
function ModelRow({ model, resetLabel, idPrefix, disabled }) {
|
|
1023
1146
|
const off = disabled || model.disabled === true;
|
|
1024
1147
|
const oneMessageId = `${idPrefix}-model-one-message`;
|
|
1025
|
-
return /* @__PURE__ */ (0,
|
|
1148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1026
1149
|
SettingRowFrame,
|
|
1027
1150
|
{
|
|
1028
1151
|
rowKey: "model",
|
|
1029
1152
|
state: model.value ? "set" : "unset",
|
|
1030
|
-
label: /* @__PURE__ */ (0,
|
|
1031
|
-
actions: model.changedHere && model.resetToInherited ? /* @__PURE__ */ (0,
|
|
1032
|
-
|
|
1153
|
+
label: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RowLabel, { children: "Model" }),
|
|
1154
|
+
actions: model.changedHere && model.resetToInherited ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1155
|
+
import_controls4.Button,
|
|
1033
1156
|
{
|
|
1034
1157
|
variant: "quiet",
|
|
1035
|
-
icon: /* @__PURE__ */ (0,
|
|
1158
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RotateCcwGlyph, {}),
|
|
1036
1159
|
onClick: () => model.resetToInherited?.(),
|
|
1037
1160
|
disabled: off,
|
|
1038
1161
|
"aria-label": `${resetLabel}: Model`,
|
|
@@ -1040,8 +1163,8 @@ function ModelRow({ model, resetLabel, idPrefix, disabled }) {
|
|
|
1040
1163
|
"data-setting-reset": "model"
|
|
1041
1164
|
}
|
|
1042
1165
|
) : null,
|
|
1043
|
-
children: /* @__PURE__ */ (0,
|
|
1044
|
-
/* @__PURE__ */ (0,
|
|
1166
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex min-h-7 min-w-0 flex-wrap items-center gap-x-2", children: [
|
|
1167
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1045
1168
|
import_react2.ModelListDropdown,
|
|
1046
1169
|
{
|
|
1047
1170
|
"aria-label": "Model",
|
|
@@ -1058,9 +1181,9 @@ function ModelRow({ model, resetLabel, idPrefix, disabled }) {
|
|
|
1058
1181
|
...model.disabledTitle ? { disabledTitle: model.disabledTitle } : {}
|
|
1059
1182
|
}
|
|
1060
1183
|
),
|
|
1061
|
-
model.oneMessage ? /* @__PURE__ */ (0,
|
|
1062
|
-
/* @__PURE__ */ (0,
|
|
1063
|
-
|
|
1184
|
+
model.oneMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { htmlFor: oneMessageId, className: "flex min-h-7 items-center gap-1 type-secondary text-muted-foreground", title: "Use this model for the next message, then go back", children: [
|
|
1185
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1186
|
+
import_controls4.Switch,
|
|
1064
1187
|
{
|
|
1065
1188
|
id: oneMessageId,
|
|
1066
1189
|
checked: model.oneMessage.on,
|
|
@@ -1081,7 +1204,6 @@ function ModelSettingsPanel({
|
|
|
1081
1204
|
idPrefix,
|
|
1082
1205
|
model,
|
|
1083
1206
|
notices,
|
|
1084
|
-
renderRow,
|
|
1085
1207
|
capabilities,
|
|
1086
1208
|
emptyNote,
|
|
1087
1209
|
disabled = false
|
|
@@ -1089,7 +1211,8 @@ function ModelSettingsPanel({
|
|
|
1089
1211
|
const groups = controls ? buildSettingsRows(controls, values).filter((group) => group.rows.length > 0) : [];
|
|
1090
1212
|
const extras = extraSettingKeys(controls, values, target.changedKeys);
|
|
1091
1213
|
const resetLabel = target.resetLabel ?? "Reset to agent";
|
|
1092
|
-
const
|
|
1214
|
+
const multiSpeaker = settingControl(controls, "multi_speaker");
|
|
1215
|
+
const extraRow = (key, kind) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1093
1216
|
ExtraSettingRow,
|
|
1094
1217
|
{
|
|
1095
1218
|
rowKey: key,
|
|
@@ -1103,29 +1226,28 @@ function ModelSettingsPanel({
|
|
|
1103
1226
|
},
|
|
1104
1227
|
key
|
|
1105
1228
|
);
|
|
1106
|
-
return /* @__PURE__ */ (0,
|
|
1107
|
-
model ? /* @__PURE__ */ (0,
|
|
1229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { "data-model-settings-panel": "", className: "@container flex min-w-0 flex-col", children: [
|
|
1230
|
+
model ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ModelRow, { model, resetLabel, idPrefix, disabled }) : null,
|
|
1108
1231
|
notices,
|
|
1109
1232
|
extras.unsupported.map((key) => extraRow(key, "unsupported")),
|
|
1110
|
-
extras.translated.length > 0 ? /* @__PURE__ */ (0,
|
|
1111
|
-
groups.length === 0 && emptyNote ? /* @__PURE__ */ (0,
|
|
1112
|
-
groups.map((group) => /* @__PURE__ */ (0,
|
|
1113
|
-
const custom = renderRow?.(row);
|
|
1114
|
-
if (custom !== void 0) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: custom }, row.key);
|
|
1233
|
+
extras.translated.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SettingsGroupSection, { id: "translated", title: "Translated for this model", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { "data-translated-settings": "", children: extras.translated.map((key) => extraRow(key, "translated")) }) }) : null,
|
|
1234
|
+
groups.length === 0 && emptyNote ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "py-2 type-secondary text-muted-foreground", children: emptyNote }) : null,
|
|
1235
|
+
groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SettingsGroupSection, { id: group.id, title: group.label || void 0, children: group.rows.map((row) => {
|
|
1115
1236
|
if (!row.control) return null;
|
|
1116
|
-
return /* @__PURE__ */ (0,
|
|
1237
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1117
1238
|
ModelSettingRow,
|
|
1118
1239
|
{
|
|
1119
1240
|
row,
|
|
1120
1241
|
control: row.control,
|
|
1121
1242
|
target,
|
|
1122
1243
|
idPrefix,
|
|
1123
|
-
disabled
|
|
1244
|
+
disabled,
|
|
1245
|
+
multiSpeaker
|
|
1124
1246
|
},
|
|
1125
1247
|
row.key
|
|
1126
1248
|
);
|
|
1127
1249
|
}) }, group.id)),
|
|
1128
|
-
capabilities ? /* @__PURE__ */ (0,
|
|
1250
|
+
capabilities ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1129
1251
|
InputCapabilitiesEditor,
|
|
1130
1252
|
{
|
|
1131
1253
|
values: capabilities.values,
|
|
@@ -167,49 +167,6 @@ interface SettingsStore {
|
|
|
167
167
|
cancelModelSwitch(agentId: string): void;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
/**
|
|
171
|
-
* Model Settings Catalog — the single source of truth for the STANDARD
|
|
172
|
-
* settings list, and the one chokepoint that decides which keys it contains.
|
|
173
|
-
*
|
|
174
|
-
* ── The model (two distinct surfaces) ────────────────────────────────────────
|
|
175
|
-
* 1. STANDARD list — ONLY the keys the selected model explicitly declares in
|
|
176
|
-
* its `controls` config (i.e. the parameters this model actually supports).
|
|
177
|
-
* `buildSettingsRows()` returns exactly these, grouped + ordered. Catalog
|
|
178
|
-
* keys the model does not declare are NOT shown here.
|
|
179
|
-
* 2. CAUTION surface — settings the agent has SET that the model does NOT
|
|
180
|
-
* support. These are never hidden: they are flagged as "not valid for this
|
|
181
|
-
* model" and made repairable by the validation layer (the IssueTable, fed
|
|
182
|
-
* by the `unsupported_by_model` rule). They do NOT belong in the standard
|
|
183
|
-
* list — that is exactly the "showing all possible keys" bug.
|
|
184
|
-
*
|
|
185
|
-
* The catalog exists so the standard list's labels, grouping and order live
|
|
186
|
-
* in ONE place (previously copy-pasted as `textModelSettings` /
|
|
187
|
-
* `booleanSettings` / ... into three components, each filtering by
|
|
188
|
-
* `getControl(key)` inline — which drifted and regressed). Components map over
|
|
189
|
-
* `buildSettingsRows()`; they must not filter by model themselves (ESLint
|
|
190
|
-
* enforces). The original recurring bug — set values silently dropped when a
|
|
191
|
-
* model didn't support them — is fixed by the CAUTION surface, not by dumping
|
|
192
|
-
* every key into the standard list.
|
|
193
|
-
*
|
|
194
|
-
* Guardrail: `settings-catalogue.test.ts` asserts the standard list contains
|
|
195
|
-
* ONLY supported keys (never the full catalog), and `unsupported-by-model.
|
|
196
|
-
* test.ts` asserts set-but-unsupported keys surface in the caution layer.
|
|
197
|
-
*/
|
|
198
|
-
|
|
199
|
-
type SettingsGroupId = "text" | "featureFlags" | "imageVideo" | "audio" | "other";
|
|
200
|
-
interface SettingsRow {
|
|
201
|
-
key: string;
|
|
202
|
-
label: string;
|
|
203
|
-
group: SettingsGroupId;
|
|
204
|
-
/** The model's control definition for this key. Standard rows are always
|
|
205
|
-
* supported, so this is present; typed nullable for consumer convenience. */
|
|
206
|
-
control: ControlDefinition | null;
|
|
207
|
-
/** Always true for rows returned by buildSettingsRows (standard = supported). */
|
|
208
|
-
supported: boolean;
|
|
209
|
-
/** True when the current settings hold a non-null value for this key. */
|
|
210
|
-
hasValue: boolean;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
170
|
/**
|
|
214
171
|
* UI Gates — canonical model-gated UI flags.
|
|
215
172
|
*
|
|
@@ -303,6 +260,11 @@ interface SettingsWriteTarget {
|
|
|
303
260
|
read(key: string, control: ControlDefinition | null): SettingRowRead;
|
|
304
261
|
/** The person edited the control. */
|
|
305
262
|
change(key: string, value: unknown, control: ControlDefinition | null): void;
|
|
263
|
+
/**
|
|
264
|
+
* Several settings that are one choice, written together (the Voice row's `tts_voice` +
|
|
265
|
+
* `multi_speaker`). Without it the panel calls `change` once per key.
|
|
266
|
+
*/
|
|
267
|
+
changeMany?(changes: Record<string, unknown>): void;
|
|
306
268
|
/** The person ticked an unset row (store `startingValueFor`). */
|
|
307
269
|
turnOn(key: string, control: ControlDefinition): void;
|
|
308
270
|
/** The person cleared the row back to "not set". */
|
|
@@ -383,41 +345,13 @@ interface ModelSettingsPanelProps {
|
|
|
383
345
|
model?: ModelRowTarget | undefined;
|
|
384
346
|
/** Drawn between the model row and the groups: notices, the issue list. */
|
|
385
347
|
notices?: ReactNode;
|
|
386
|
-
/** A row the host draws itself (the multi-speaker voice editor); `undefined` = the standard row. */
|
|
387
|
-
renderRow?: (row: SettingsRow) => ReactNode | undefined;
|
|
388
348
|
/** The input capabilities group, under the settings groups. */
|
|
389
349
|
capabilities?: CapabilitiesWriteTarget | undefined;
|
|
390
350
|
/** Said where the rows would be when the model declares none (or no model is chosen). */
|
|
391
351
|
emptyNote?: ReactNode;
|
|
392
352
|
disabled?: boolean;
|
|
393
353
|
}
|
|
394
|
-
declare function ModelSettingsPanel({ controls, values, target, idPrefix, model, notices,
|
|
395
|
-
|
|
396
|
-
/** A catalog value as the person reads it ("On", "auto", "1024"). */
|
|
397
|
-
declare function formatSettingValue(value: unknown): string;
|
|
398
|
-
interface SettingRowFrameProps {
|
|
399
|
-
/** `data-setting-row` — the setting key (or a host row name such as "model"). */
|
|
400
|
-
rowKey: string;
|
|
401
|
-
/** `data-setting-state` — unset | set | off | bound | translated | … */
|
|
402
|
-
state?: string;
|
|
403
|
-
/** The 16px leading column: the row's checkbox, or an icon. */
|
|
404
|
-
leading?: ReactNode;
|
|
405
|
-
label: ReactNode;
|
|
406
|
-
/** The control, or the row's value text. */
|
|
407
|
-
children?: ReactNode;
|
|
408
|
-
/** Fixed-width icons on the right: status, then actions. */
|
|
409
|
-
actions?: ReactNode;
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* The one row geometry every line of the panel uses — setting rows, the model row, the
|
|
413
|
-
* translated rows, the voice row and the input capabilities — so their edges line up.
|
|
414
|
-
*/
|
|
415
|
-
declare function SettingRowFrame({ rowKey, state, leading, label, children, actions }: SettingRowFrameProps): React.JSX.Element;
|
|
416
|
-
declare function RowLabel({ htmlFor, muted, children }: {
|
|
417
|
-
htmlFor?: string;
|
|
418
|
-
muted?: boolean;
|
|
419
|
-
children: ReactNode;
|
|
420
|
-
}): React.JSX.Element;
|
|
354
|
+
declare function ModelSettingsPanel({ controls, values, target, idPrefix, model, notices, capabilities, emptyNote, disabled, }: ModelSettingsPanelProps): React.JSX.Element;
|
|
421
355
|
|
|
422
356
|
/** Subscribe to a slice of a settings store. `select` must return a stable value for unchanged state. */
|
|
423
357
|
declare function useSettingsSelector<T>(store: SettingsStore, select: (state: AgentSettingsState) => T): T;
|
|
@@ -426,4 +360,4 @@ declare function useSettingsEntry(store: SettingsStore, agentId: string | null |
|
|
|
426
360
|
/** Defaults merged with overrides for one agent; recomputed only when the entry changes. */
|
|
427
361
|
declare function useEffectiveSettings(store: SettingsStore, agentId: string | null | undefined): Partial<AgentSettings>;
|
|
428
362
|
|
|
429
|
-
export { ModelSettingsPanel, type ModelSettingsPanelProps,
|
|
363
|
+
export { ModelSettingsPanel, type ModelSettingsPanelProps, useEffectiveSettings, useSettingsEntry, useSettingsSelector };
|
|
@@ -167,49 +167,6 @@ interface SettingsStore {
|
|
|
167
167
|
cancelModelSwitch(agentId: string): void;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
/**
|
|
171
|
-
* Model Settings Catalog — the single source of truth for the STANDARD
|
|
172
|
-
* settings list, and the one chokepoint that decides which keys it contains.
|
|
173
|
-
*
|
|
174
|
-
* ── The model (two distinct surfaces) ────────────────────────────────────────
|
|
175
|
-
* 1. STANDARD list — ONLY the keys the selected model explicitly declares in
|
|
176
|
-
* its `controls` config (i.e. the parameters this model actually supports).
|
|
177
|
-
* `buildSettingsRows()` returns exactly these, grouped + ordered. Catalog
|
|
178
|
-
* keys the model does not declare are NOT shown here.
|
|
179
|
-
* 2. CAUTION surface — settings the agent has SET that the model does NOT
|
|
180
|
-
* support. These are never hidden: they are flagged as "not valid for this
|
|
181
|
-
* model" and made repairable by the validation layer (the IssueTable, fed
|
|
182
|
-
* by the `unsupported_by_model` rule). They do NOT belong in the standard
|
|
183
|
-
* list — that is exactly the "showing all possible keys" bug.
|
|
184
|
-
*
|
|
185
|
-
* The catalog exists so the standard list's labels, grouping and order live
|
|
186
|
-
* in ONE place (previously copy-pasted as `textModelSettings` /
|
|
187
|
-
* `booleanSettings` / ... into three components, each filtering by
|
|
188
|
-
* `getControl(key)` inline — which drifted and regressed). Components map over
|
|
189
|
-
* `buildSettingsRows()`; they must not filter by model themselves (ESLint
|
|
190
|
-
* enforces). The original recurring bug — set values silently dropped when a
|
|
191
|
-
* model didn't support them — is fixed by the CAUTION surface, not by dumping
|
|
192
|
-
* every key into the standard list.
|
|
193
|
-
*
|
|
194
|
-
* Guardrail: `settings-catalogue.test.ts` asserts the standard list contains
|
|
195
|
-
* ONLY supported keys (never the full catalog), and `unsupported-by-model.
|
|
196
|
-
* test.ts` asserts set-but-unsupported keys surface in the caution layer.
|
|
197
|
-
*/
|
|
198
|
-
|
|
199
|
-
type SettingsGroupId = "text" | "featureFlags" | "imageVideo" | "audio" | "other";
|
|
200
|
-
interface SettingsRow {
|
|
201
|
-
key: string;
|
|
202
|
-
label: string;
|
|
203
|
-
group: SettingsGroupId;
|
|
204
|
-
/** The model's control definition for this key. Standard rows are always
|
|
205
|
-
* supported, so this is present; typed nullable for consumer convenience. */
|
|
206
|
-
control: ControlDefinition | null;
|
|
207
|
-
/** Always true for rows returned by buildSettingsRows (standard = supported). */
|
|
208
|
-
supported: boolean;
|
|
209
|
-
/** True when the current settings hold a non-null value for this key. */
|
|
210
|
-
hasValue: boolean;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
170
|
/**
|
|
214
171
|
* UI Gates — canonical model-gated UI flags.
|
|
215
172
|
*
|
|
@@ -303,6 +260,11 @@ interface SettingsWriteTarget {
|
|
|
303
260
|
read(key: string, control: ControlDefinition | null): SettingRowRead;
|
|
304
261
|
/** The person edited the control. */
|
|
305
262
|
change(key: string, value: unknown, control: ControlDefinition | null): void;
|
|
263
|
+
/**
|
|
264
|
+
* Several settings that are one choice, written together (the Voice row's `tts_voice` +
|
|
265
|
+
* `multi_speaker`). Without it the panel calls `change` once per key.
|
|
266
|
+
*/
|
|
267
|
+
changeMany?(changes: Record<string, unknown>): void;
|
|
306
268
|
/** The person ticked an unset row (store `startingValueFor`). */
|
|
307
269
|
turnOn(key: string, control: ControlDefinition): void;
|
|
308
270
|
/** The person cleared the row back to "not set". */
|
|
@@ -383,41 +345,13 @@ interface ModelSettingsPanelProps {
|
|
|
383
345
|
model?: ModelRowTarget | undefined;
|
|
384
346
|
/** Drawn between the model row and the groups: notices, the issue list. */
|
|
385
347
|
notices?: ReactNode;
|
|
386
|
-
/** A row the host draws itself (the multi-speaker voice editor); `undefined` = the standard row. */
|
|
387
|
-
renderRow?: (row: SettingsRow) => ReactNode | undefined;
|
|
388
348
|
/** The input capabilities group, under the settings groups. */
|
|
389
349
|
capabilities?: CapabilitiesWriteTarget | undefined;
|
|
390
350
|
/** Said where the rows would be when the model declares none (or no model is chosen). */
|
|
391
351
|
emptyNote?: ReactNode;
|
|
392
352
|
disabled?: boolean;
|
|
393
353
|
}
|
|
394
|
-
declare function ModelSettingsPanel({ controls, values, target, idPrefix, model, notices,
|
|
395
|
-
|
|
396
|
-
/** A catalog value as the person reads it ("On", "auto", "1024"). */
|
|
397
|
-
declare function formatSettingValue(value: unknown): string;
|
|
398
|
-
interface SettingRowFrameProps {
|
|
399
|
-
/** `data-setting-row` — the setting key (or a host row name such as "model"). */
|
|
400
|
-
rowKey: string;
|
|
401
|
-
/** `data-setting-state` — unset | set | off | bound | translated | … */
|
|
402
|
-
state?: string;
|
|
403
|
-
/** The 16px leading column: the row's checkbox, or an icon. */
|
|
404
|
-
leading?: ReactNode;
|
|
405
|
-
label: ReactNode;
|
|
406
|
-
/** The control, or the row's value text. */
|
|
407
|
-
children?: ReactNode;
|
|
408
|
-
/** Fixed-width icons on the right: status, then actions. */
|
|
409
|
-
actions?: ReactNode;
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* The one row geometry every line of the panel uses — setting rows, the model row, the
|
|
413
|
-
* translated rows, the voice row and the input capabilities — so their edges line up.
|
|
414
|
-
*/
|
|
415
|
-
declare function SettingRowFrame({ rowKey, state, leading, label, children, actions }: SettingRowFrameProps): React.JSX.Element;
|
|
416
|
-
declare function RowLabel({ htmlFor, muted, children }: {
|
|
417
|
-
htmlFor?: string;
|
|
418
|
-
muted?: boolean;
|
|
419
|
-
children: ReactNode;
|
|
420
|
-
}): React.JSX.Element;
|
|
354
|
+
declare function ModelSettingsPanel({ controls, values, target, idPrefix, model, notices, capabilities, emptyNote, disabled, }: ModelSettingsPanelProps): React.JSX.Element;
|
|
421
355
|
|
|
422
356
|
/** Subscribe to a slice of a settings store. `select` must return a stable value for unchanged state. */
|
|
423
357
|
declare function useSettingsSelector<T>(store: SettingsStore, select: (state: AgentSettingsState) => T): T;
|
|
@@ -426,4 +360,4 @@ declare function useSettingsEntry(store: SettingsStore, agentId: string | null |
|
|
|
426
360
|
/** Defaults merged with overrides for one agent; recomputed only when the entry changes. */
|
|
427
361
|
declare function useEffectiveSettings(store: SettingsStore, agentId: string | null | undefined): Partial<AgentSettings>;
|
|
428
362
|
|
|
429
|
-
export { ModelSettingsPanel, type ModelSettingsPanelProps,
|
|
363
|
+
export { ModelSettingsPanel, type ModelSettingsPanelProps, useEffectiveSettings, useSettingsEntry, useSettingsSelector };
|
|
@@ -181,7 +181,7 @@ function readEffectiveSettings(entry) {
|
|
|
181
181
|
|
|
182
182
|
// settings/react/ModelSettingsPanel.tsx
|
|
183
183
|
import { Checkbox as Checkbox2 } from "@ai-matrx/design-system";
|
|
184
|
-
import { Button as
|
|
184
|
+
import { Button as Button3, Chip, Switch as Switch2 } from "@ai-matrx/design-system/controls";
|
|
185
185
|
import { ModelListDropdown } from "@ai-matrx/agents/models/react";
|
|
186
186
|
|
|
187
187
|
// settings/settings-catalogue.ts
|
|
@@ -297,6 +297,9 @@ var CATCHALL_EXCLUDED = /* @__PURE__ */ new Set([
|
|
|
297
297
|
// model now declares `tools` for the tool-support capability).
|
|
298
298
|
...UI_GATE_KEYS
|
|
299
299
|
]);
|
|
300
|
+
function settingControl(controls, key) {
|
|
301
|
+
return lookupControl(controls, key);
|
|
302
|
+
}
|
|
300
303
|
function lookupControl(controls, key) {
|
|
301
304
|
if (!controls) return null;
|
|
302
305
|
if (CATCHALL_EXCLUDED.has(key)) {
|
|
@@ -865,29 +868,142 @@ function NumberInput({
|
|
|
865
868
|
);
|
|
866
869
|
}
|
|
867
870
|
|
|
868
|
-
// settings/react/
|
|
871
|
+
// settings/react/VoiceSettingControl.tsx
|
|
872
|
+
import { Button as Button2, Field, SegmentedControl, Select as Select2 } from "@ai-matrx/design-system/controls";
|
|
873
|
+
import { PlusIcon, XIcon } from "@ai-matrx/design-system/icons";
|
|
869
874
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
875
|
+
function speakersOf(value, voices) {
|
|
876
|
+
if (!Array.isArray(value)) return [];
|
|
877
|
+
return value.map((entry, index) => {
|
|
878
|
+
const record = entry !== null && typeof entry === "object" ? entry : {};
|
|
879
|
+
return {
|
|
880
|
+
name: typeof record.name === "string" ? record.name : `Speaker ${index + 1}`,
|
|
881
|
+
voice: typeof record.voice === "string" ? record.voice : voices[0] ?? ""
|
|
882
|
+
};
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
function VoiceSettingControl({ voices, value, multiSpeaker, onChange, idPrefix, disabled = false }) {
|
|
886
|
+
const isMulti = Array.isArray(value);
|
|
887
|
+
const speakers = speakersOf(value, voices);
|
|
888
|
+
const single = typeof value === "string" && value ? value : voices[0] ?? "";
|
|
889
|
+
const max = multiSpeaker?.max !== void 0 && multiSpeaker.max > 0 ? multiSpeaker.max : void 0;
|
|
890
|
+
const canAdd = max === void 0 || speakers.length < max;
|
|
891
|
+
const options = voices.map((voice) => ({ value: voice, label: voice }));
|
|
892
|
+
const voiceSelect = (current, label, pick) => /* @__PURE__ */ jsx4(
|
|
893
|
+
Select2,
|
|
894
|
+
{
|
|
895
|
+
value: current,
|
|
896
|
+
options: options.some((o) => o.value === current) ? options : [{ value: current, label: current }, ...options],
|
|
897
|
+
onValueChange: pick,
|
|
898
|
+
"aria-label": label,
|
|
899
|
+
disabled,
|
|
900
|
+
className: "min-w-0"
|
|
901
|
+
}
|
|
902
|
+
);
|
|
903
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 flex-col gap-1", "data-voice-control": "", children: [
|
|
904
|
+
multiSpeaker || isMulti ? /* @__PURE__ */ jsx4(
|
|
905
|
+
SegmentedControl,
|
|
906
|
+
{
|
|
907
|
+
"aria-label": "Voices",
|
|
908
|
+
value: isMulti ? "multi" : "single",
|
|
909
|
+
onValueChange: (next) => {
|
|
910
|
+
if (next === "multi" && !isMulti) {
|
|
911
|
+
onChange(
|
|
912
|
+
[
|
|
913
|
+
{ name: "Speaker 1", voice: single },
|
|
914
|
+
{ name: "Speaker 2", voice: voices[1] ?? single }
|
|
915
|
+
],
|
|
916
|
+
true
|
|
917
|
+
);
|
|
918
|
+
} else if (next === "single" && isMulti) {
|
|
919
|
+
onChange(speakers[0]?.voice || voices[0] || "", false);
|
|
920
|
+
}
|
|
921
|
+
},
|
|
922
|
+
data: [
|
|
923
|
+
{ value: "single", label: "One voice", disabled },
|
|
924
|
+
{ value: "multi", label: "Speakers", disabled: disabled || !multiSpeaker }
|
|
925
|
+
]
|
|
926
|
+
}
|
|
927
|
+
) : null,
|
|
928
|
+
!isMulti ? voiceSelect(single, "Voice", (next) => onChange(next, false)) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
929
|
+
speakers.map((speaker, index) => /* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 items-center gap-1", "data-speaker": index, children: [
|
|
930
|
+
/* @__PURE__ */ jsx4(
|
|
931
|
+
Field,
|
|
932
|
+
{
|
|
933
|
+
id: `${idPrefix}-speaker-${index}`,
|
|
934
|
+
"aria-label": `Speaker ${index + 1} name`,
|
|
935
|
+
value: speaker.name,
|
|
936
|
+
onChange: (event) => onChange(
|
|
937
|
+
speakers.map((s, i) => i === index ? { ...s, name: event.target.value } : s),
|
|
938
|
+
true
|
|
939
|
+
),
|
|
940
|
+
disabled,
|
|
941
|
+
className: "min-w-0 flex-1"
|
|
942
|
+
}
|
|
943
|
+
),
|
|
944
|
+
voiceSelect(
|
|
945
|
+
speaker.voice,
|
|
946
|
+
`Speaker ${index + 1} voice`,
|
|
947
|
+
(next) => onChange(
|
|
948
|
+
speakers.map((s, i) => i === index ? { ...s, voice: next } : s),
|
|
949
|
+
true
|
|
950
|
+
)
|
|
951
|
+
),
|
|
952
|
+
/* @__PURE__ */ jsx4(
|
|
953
|
+
Button2,
|
|
954
|
+
{
|
|
955
|
+
variant: "quiet",
|
|
956
|
+
removes: true,
|
|
957
|
+
icon: /* @__PURE__ */ jsx4(XIcon, {}),
|
|
958
|
+
onClick: () => onChange(speakers.filter((_, i) => i !== index), true),
|
|
959
|
+
disabled: disabled || speakers.length <= 2,
|
|
960
|
+
"aria-label": `Remove speaker ${index + 1}`,
|
|
961
|
+
title: "Remove speaker"
|
|
962
|
+
}
|
|
963
|
+
)
|
|
964
|
+
] }, index)),
|
|
965
|
+
/* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4(
|
|
966
|
+
Button2,
|
|
967
|
+
{
|
|
968
|
+
variant: "quiet",
|
|
969
|
+
icon: /* @__PURE__ */ jsx4(PlusIcon, {}),
|
|
970
|
+
onClick: () => onChange([...speakers, { name: `Speaker ${speakers.length + 1}`, voice: voices[0] ?? "" }], true),
|
|
971
|
+
disabled: disabled || !canAdd,
|
|
972
|
+
title: canAdd ? "Add a speaker" : `This model takes up to ${max} speakers`,
|
|
973
|
+
children: "Add speaker"
|
|
974
|
+
}
|
|
975
|
+
) })
|
|
976
|
+
] })
|
|
977
|
+
] });
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// settings/react/ModelSettingsPanel.tsx
|
|
981
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
870
982
|
function StatusGlyph({ issue, source }) {
|
|
871
983
|
const title = issue ? issue.message : source ? `Valid \xB7 ${source}` : "Valid";
|
|
872
|
-
return /* @__PURE__ */
|
|
984
|
+
return /* @__PURE__ */ jsx5(
|
|
873
985
|
"span",
|
|
874
986
|
{
|
|
875
987
|
className: cn("inline-flex h-7 w-6 shrink-0 items-center justify-center", issue ? "text-warning" : "text-success"),
|
|
876
988
|
role: "img",
|
|
877
989
|
"aria-label": title,
|
|
878
990
|
title,
|
|
879
|
-
children: issue ? /* @__PURE__ */
|
|
991
|
+
children: issue ? /* @__PURE__ */ jsx5(TriangleAlertGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx5(CircleCheckGlyph, { className: "h-3.5 w-3.5" })
|
|
880
992
|
}
|
|
881
993
|
);
|
|
882
994
|
}
|
|
883
|
-
function
|
|
995
|
+
function changeTogether(target, changes, controls) {
|
|
996
|
+
if (target.changeMany) target.changeMany(changes);
|
|
997
|
+
else for (const [key, value] of Object.entries(changes)) target.change(key, value, controls[key] ?? null);
|
|
998
|
+
}
|
|
999
|
+
function ModelSettingRow({ row, control, target, idPrefix, disabled, multiSpeaker }) {
|
|
884
1000
|
const read = target.read(row.key, control);
|
|
885
1001
|
const resetLabel = target.resetLabel ?? "Reset to agent";
|
|
886
|
-
const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */
|
|
887
|
-
|
|
1002
|
+
const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */ jsx5(
|
|
1003
|
+
Button3,
|
|
888
1004
|
{
|
|
889
1005
|
variant: "quiet",
|
|
890
|
-
icon: /* @__PURE__ */
|
|
1006
|
+
icon: /* @__PURE__ */ jsx5(RotateCcwGlyph, {}),
|
|
891
1007
|
onClick: () => target.resetToInherited?.(row.key),
|
|
892
1008
|
disabled,
|
|
893
1009
|
"aria-label": `${resetLabel}: ${row.label}`,
|
|
@@ -896,20 +1012,20 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
896
1012
|
}
|
|
897
1013
|
) : null;
|
|
898
1014
|
if (read.state === "bound") {
|
|
899
|
-
return /* @__PURE__ */
|
|
1015
|
+
return /* @__PURE__ */ jsx5(
|
|
900
1016
|
SettingRowFrame,
|
|
901
1017
|
{
|
|
902
1018
|
rowKey: row.key,
|
|
903
1019
|
state: "bound",
|
|
904
|
-
leading: /* @__PURE__ */
|
|
905
|
-
label: /* @__PURE__ */
|
|
906
|
-
actions: /* @__PURE__ */
|
|
1020
|
+
leading: /* @__PURE__ */ jsx5(Checkbox2, { checked: true, disabled: true, "aria-label": `${row.label} is a run input` }),
|
|
1021
|
+
label: /* @__PURE__ */ jsx5(RowLabel, { children: row.label }),
|
|
1022
|
+
actions: /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
907
1023
|
reset,
|
|
908
|
-
target.unbind ? /* @__PURE__ */
|
|
909
|
-
|
|
1024
|
+
target.unbind ? /* @__PURE__ */ jsx5(
|
|
1025
|
+
Button3,
|
|
910
1026
|
{
|
|
911
1027
|
variant: "quiet",
|
|
912
|
-
icon: /* @__PURE__ */
|
|
1028
|
+
icon: /* @__PURE__ */ jsx5(UnlinkGlyph, {}),
|
|
913
1029
|
onClick: () => target.unbind?.(row.key, control),
|
|
914
1030
|
disabled,
|
|
915
1031
|
"aria-label": `Make ${row.label} a fixed setting`,
|
|
@@ -917,9 +1033,9 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
917
1033
|
}
|
|
918
1034
|
) : null
|
|
919
1035
|
] }),
|
|
920
|
-
children: /* @__PURE__ */
|
|
921
|
-
/* @__PURE__ */
|
|
922
|
-
/* @__PURE__ */
|
|
1036
|
+
children: /* @__PURE__ */ jsxs5("span", { className: "flex min-h-7 min-w-0 items-center gap-2", "data-bound-control": row.key, children: [
|
|
1037
|
+
/* @__PURE__ */ jsx5(Chip, { tone: "primary", icon: /* @__PURE__ */ jsx5(VariableGlyph, {}), label: `{{${read.variableName}}}` }),
|
|
1038
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate type-meta text-muted-foreground", children: read.value === void 0 || read.value === null || read.value === "" ? "Model default" : formatSettingValue(read.value) })
|
|
923
1039
|
] })
|
|
924
1040
|
}
|
|
925
1041
|
);
|
|
@@ -929,12 +1045,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
929
1045
|
const isOff = isSet && isOffValue(value, control);
|
|
930
1046
|
const checkboxId = `${idPrefix}-setting-${row.key}`;
|
|
931
1047
|
const canBind = Boolean(target.bind) && (target.canBind?.(row.key) ?? true);
|
|
932
|
-
return /* @__PURE__ */
|
|
1048
|
+
return /* @__PURE__ */ jsx5(
|
|
933
1049
|
SettingRowFrame,
|
|
934
1050
|
{
|
|
935
1051
|
rowKey: row.key,
|
|
936
1052
|
state: isOff ? "off" : read.state,
|
|
937
|
-
leading: /* @__PURE__ */
|
|
1053
|
+
leading: /* @__PURE__ */ jsx5(
|
|
938
1054
|
Checkbox2,
|
|
939
1055
|
{
|
|
940
1056
|
id: checkboxId,
|
|
@@ -943,14 +1059,14 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
943
1059
|
onCheckedChange: (next) => next === true ? target.turnOn(row.key, control) : target.clear(row.key)
|
|
944
1060
|
}
|
|
945
1061
|
),
|
|
946
|
-
label: /* @__PURE__ */
|
|
947
|
-
actions: /* @__PURE__ */
|
|
948
|
-
/* @__PURE__ */
|
|
949
|
-
canBind ? /* @__PURE__ */
|
|
950
|
-
|
|
1062
|
+
label: /* @__PURE__ */ jsx5(RowLabel, { htmlFor: checkboxId, muted: !isSet, children: row.label }),
|
|
1063
|
+
actions: /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1064
|
+
/* @__PURE__ */ jsx5(StatusGlyph, { issue: read.issue, source: read.source }),
|
|
1065
|
+
canBind ? /* @__PURE__ */ jsx5(
|
|
1066
|
+
Button3,
|
|
951
1067
|
{
|
|
952
1068
|
variant: "quiet",
|
|
953
|
-
icon: /* @__PURE__ */
|
|
1069
|
+
icon: /* @__PURE__ */ jsx5(VariableGlyph, {}),
|
|
954
1070
|
onClick: () => target.bind?.(row.key, control),
|
|
955
1071
|
disabled,
|
|
956
1072
|
"aria-label": `Make ${row.label} a run input`,
|
|
@@ -958,11 +1074,11 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
958
1074
|
"data-bind-control": row.key
|
|
959
1075
|
}
|
|
960
1076
|
) : null,
|
|
961
|
-
isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */
|
|
962
|
-
|
|
1077
|
+
isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */ jsx5(
|
|
1078
|
+
Button3,
|
|
963
1079
|
{
|
|
964
1080
|
variant: "quiet",
|
|
965
|
-
icon: /* @__PURE__ */
|
|
1081
|
+
icon: /* @__PURE__ */ jsx5(WrenchGlyph, {}),
|
|
966
1082
|
onClick: () => target.fix?.(row.key),
|
|
967
1083
|
disabled,
|
|
968
1084
|
"aria-label": `Fix ${row.label} automatically`,
|
|
@@ -970,12 +1086,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
970
1086
|
}
|
|
971
1087
|
) : null,
|
|
972
1088
|
reset,
|
|
973
|
-
isSet ? /* @__PURE__ */
|
|
974
|
-
|
|
1089
|
+
isSet ? /* @__PURE__ */ jsx5(
|
|
1090
|
+
Button3,
|
|
975
1091
|
{
|
|
976
1092
|
variant: "quiet",
|
|
977
1093
|
removes: true,
|
|
978
|
-
icon: /* @__PURE__ */
|
|
1094
|
+
icon: /* @__PURE__ */ jsx5(Trash2Glyph, {}),
|
|
979
1095
|
onClick: () => target.clear(row.key),
|
|
980
1096
|
disabled,
|
|
981
1097
|
"aria-label": `Clear ${row.label} to not set`,
|
|
@@ -984,8 +1100,18 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
984
1100
|
}
|
|
985
1101
|
) : null
|
|
986
1102
|
] }),
|
|
987
|
-
children: isSet ? /* @__PURE__ */
|
|
988
|
-
|
|
1103
|
+
children: isSet && row.key === "tts_voice" && control.enum?.length && (multiSpeaker || Array.isArray(value)) ? /* @__PURE__ */ jsx5(
|
|
1104
|
+
VoiceSettingControl,
|
|
1105
|
+
{
|
|
1106
|
+
voices: control.enum.map(String),
|
|
1107
|
+
value,
|
|
1108
|
+
multiSpeaker: multiSpeaker ? { max: multiSpeaker.max } : null,
|
|
1109
|
+
onChange: (voice, multi) => changeTogether(target, { tts_voice: voice, multi_speaker: multi }, { tts_voice: control, multi_speaker: multiSpeaker }),
|
|
1110
|
+
idPrefix: `${idPrefix}-voice`,
|
|
1111
|
+
disabled
|
|
1112
|
+
}
|
|
1113
|
+
) : isSet ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1114
|
+
/* @__PURE__ */ jsx5(
|
|
989
1115
|
SettingControlInput,
|
|
990
1116
|
{
|
|
991
1117
|
settingKey: row.key,
|
|
@@ -996,40 +1122,40 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
996
1122
|
id: `${idPrefix}-control-${row.key}`
|
|
997
1123
|
}
|
|
998
1124
|
),
|
|
999
|
-
read.issue ? /* @__PURE__ */
|
|
1000
|
-
] }) : /* @__PURE__ */
|
|
1125
|
+
read.issue ? /* @__PURE__ */ jsx5("p", { className: "pt-1 type-meta text-warning-ink", children: read.issue.message }) : null
|
|
1126
|
+
] }) : /* @__PURE__ */ jsx5(RowText, { children: read.modelDefault !== void 0 && read.modelDefault !== null ? `Not set \xB7 Model default: ${formatSettingValue(read.modelDefault)}` : "Not set" })
|
|
1001
1127
|
}
|
|
1002
1128
|
);
|
|
1003
1129
|
}
|
|
1004
1130
|
function ExtraSettingRow({ rowKey, label, value, kind, onClear, onReset, resetLabel = "Reset to agent", disabled = false }) {
|
|
1005
|
-
return /* @__PURE__ */
|
|
1131
|
+
return /* @__PURE__ */ jsx5(
|
|
1006
1132
|
SettingRowFrame,
|
|
1007
1133
|
{
|
|
1008
1134
|
rowKey,
|
|
1009
1135
|
state: kind,
|
|
1010
|
-
label: /* @__PURE__ */
|
|
1011
|
-
actions: /* @__PURE__ */
|
|
1012
|
-
kind === "translated" ? /* @__PURE__ */
|
|
1013
|
-
onReset ? /* @__PURE__ */
|
|
1136
|
+
label: /* @__PURE__ */ jsx5(RowLabel, { children: label }),
|
|
1137
|
+
actions: /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1138
|
+
kind === "translated" ? /* @__PURE__ */ jsx5(Chip, { tone: "sky", label: "Translated", title: "Kept as set and sent as this model's closest equivalent" }) : /* @__PURE__ */ jsx5(Chip, { tone: "warning", label: "Not on this model", title: "This model has no such setting" }),
|
|
1139
|
+
onReset ? /* @__PURE__ */ jsx5(Button3, { variant: "quiet", icon: /* @__PURE__ */ jsx5(RotateCcwGlyph, {}), onClick: onReset, disabled, "aria-label": `${resetLabel}: ${label}`, title: resetLabel, "data-setting-reset": rowKey }) : /* @__PURE__ */ jsx5(Button3, { variant: "quiet", removes: true, icon: /* @__PURE__ */ jsx5(Trash2Glyph, {}), onClick: onClear, disabled, "aria-label": `Clear ${label}`, title: "Clear to not set", "data-setting-clear": rowKey })
|
|
1014
1140
|
] }),
|
|
1015
|
-
children: /* @__PURE__ */
|
|
1141
|
+
children: /* @__PURE__ */ jsx5(RowText, { mono: value !== void 0 && value !== null, children: value === void 0 || value === null ? "Not set" : isOffValue(value, null) ? "Off" : formatSettingValue(value) })
|
|
1016
1142
|
}
|
|
1017
1143
|
);
|
|
1018
1144
|
}
|
|
1019
1145
|
function ModelRow({ model, resetLabel, idPrefix, disabled }) {
|
|
1020
1146
|
const off = disabled || model.disabled === true;
|
|
1021
1147
|
const oneMessageId = `${idPrefix}-model-one-message`;
|
|
1022
|
-
return /* @__PURE__ */
|
|
1148
|
+
return /* @__PURE__ */ jsx5(
|
|
1023
1149
|
SettingRowFrame,
|
|
1024
1150
|
{
|
|
1025
1151
|
rowKey: "model",
|
|
1026
1152
|
state: model.value ? "set" : "unset",
|
|
1027
|
-
label: /* @__PURE__ */
|
|
1028
|
-
actions: model.changedHere && model.resetToInherited ? /* @__PURE__ */
|
|
1029
|
-
|
|
1153
|
+
label: /* @__PURE__ */ jsx5(RowLabel, { children: "Model" }),
|
|
1154
|
+
actions: model.changedHere && model.resetToInherited ? /* @__PURE__ */ jsx5(
|
|
1155
|
+
Button3,
|
|
1030
1156
|
{
|
|
1031
1157
|
variant: "quiet",
|
|
1032
|
-
icon: /* @__PURE__ */
|
|
1158
|
+
icon: /* @__PURE__ */ jsx5(RotateCcwGlyph, {}),
|
|
1033
1159
|
onClick: () => model.resetToInherited?.(),
|
|
1034
1160
|
disabled: off,
|
|
1035
1161
|
"aria-label": `${resetLabel}: Model`,
|
|
@@ -1037,8 +1163,8 @@ function ModelRow({ model, resetLabel, idPrefix, disabled }) {
|
|
|
1037
1163
|
"data-setting-reset": "model"
|
|
1038
1164
|
}
|
|
1039
1165
|
) : null,
|
|
1040
|
-
children: /* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1166
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "flex min-h-7 min-w-0 flex-wrap items-center gap-x-2", children: [
|
|
1167
|
+
/* @__PURE__ */ jsx5(
|
|
1042
1168
|
ModelListDropdown,
|
|
1043
1169
|
{
|
|
1044
1170
|
"aria-label": "Model",
|
|
@@ -1055,8 +1181,8 @@ function ModelRow({ model, resetLabel, idPrefix, disabled }) {
|
|
|
1055
1181
|
...model.disabledTitle ? { disabledTitle: model.disabledTitle } : {}
|
|
1056
1182
|
}
|
|
1057
1183
|
),
|
|
1058
|
-
model.oneMessage ? /* @__PURE__ */
|
|
1059
|
-
/* @__PURE__ */
|
|
1184
|
+
model.oneMessage ? /* @__PURE__ */ jsxs5("label", { htmlFor: oneMessageId, className: "flex min-h-7 items-center gap-1 type-secondary text-muted-foreground", title: "Use this model for the next message, then go back", children: [
|
|
1185
|
+
/* @__PURE__ */ jsx5(
|
|
1060
1186
|
Switch2,
|
|
1061
1187
|
{
|
|
1062
1188
|
id: oneMessageId,
|
|
@@ -1078,7 +1204,6 @@ function ModelSettingsPanel({
|
|
|
1078
1204
|
idPrefix,
|
|
1079
1205
|
model,
|
|
1080
1206
|
notices,
|
|
1081
|
-
renderRow,
|
|
1082
1207
|
capabilities,
|
|
1083
1208
|
emptyNote,
|
|
1084
1209
|
disabled = false
|
|
@@ -1086,7 +1211,8 @@ function ModelSettingsPanel({
|
|
|
1086
1211
|
const groups = controls ? buildSettingsRows(controls, values).filter((group) => group.rows.length > 0) : [];
|
|
1087
1212
|
const extras = extraSettingKeys(controls, values, target.changedKeys);
|
|
1088
1213
|
const resetLabel = target.resetLabel ?? "Reset to agent";
|
|
1089
|
-
const
|
|
1214
|
+
const multiSpeaker = settingControl(controls, "multi_speaker");
|
|
1215
|
+
const extraRow = (key, kind) => /* @__PURE__ */ jsx5(
|
|
1090
1216
|
ExtraSettingRow,
|
|
1091
1217
|
{
|
|
1092
1218
|
rowKey: key,
|
|
@@ -1100,29 +1226,28 @@ function ModelSettingsPanel({
|
|
|
1100
1226
|
},
|
|
1101
1227
|
key
|
|
1102
1228
|
);
|
|
1103
|
-
return /* @__PURE__ */
|
|
1104
|
-
model ? /* @__PURE__ */
|
|
1229
|
+
return /* @__PURE__ */ jsxs5("div", { "data-model-settings-panel": "", className: "@container flex min-w-0 flex-col", children: [
|
|
1230
|
+
model ? /* @__PURE__ */ jsx5(ModelRow, { model, resetLabel, idPrefix, disabled }) : null,
|
|
1105
1231
|
notices,
|
|
1106
1232
|
extras.unsupported.map((key) => extraRow(key, "unsupported")),
|
|
1107
|
-
extras.translated.length > 0 ? /* @__PURE__ */
|
|
1108
|
-
groups.length === 0 && emptyNote ? /* @__PURE__ */
|
|
1109
|
-
groups.map((group) => /* @__PURE__ */
|
|
1110
|
-
const custom = renderRow?.(row);
|
|
1111
|
-
if (custom !== void 0) return /* @__PURE__ */ jsx4("div", { children: custom }, row.key);
|
|
1233
|
+
extras.translated.length > 0 ? /* @__PURE__ */ jsx5(SettingsGroupSection, { id: "translated", title: "Translated for this model", children: /* @__PURE__ */ jsx5("div", { "data-translated-settings": "", children: extras.translated.map((key) => extraRow(key, "translated")) }) }) : null,
|
|
1234
|
+
groups.length === 0 && emptyNote ? /* @__PURE__ */ jsx5("div", { className: "py-2 type-secondary text-muted-foreground", children: emptyNote }) : null,
|
|
1235
|
+
groups.map((group) => /* @__PURE__ */ jsx5(SettingsGroupSection, { id: group.id, title: group.label || void 0, children: group.rows.map((row) => {
|
|
1112
1236
|
if (!row.control) return null;
|
|
1113
|
-
return /* @__PURE__ */
|
|
1237
|
+
return /* @__PURE__ */ jsx5(
|
|
1114
1238
|
ModelSettingRow,
|
|
1115
1239
|
{
|
|
1116
1240
|
row,
|
|
1117
1241
|
control: row.control,
|
|
1118
1242
|
target,
|
|
1119
1243
|
idPrefix,
|
|
1120
|
-
disabled
|
|
1244
|
+
disabled,
|
|
1245
|
+
multiSpeaker
|
|
1121
1246
|
},
|
|
1122
1247
|
row.key
|
|
1123
1248
|
);
|
|
1124
1249
|
}) }, group.id)),
|
|
1125
|
-
capabilities ? /* @__PURE__ */
|
|
1250
|
+
capabilities ? /* @__PURE__ */ jsx5(
|
|
1126
1251
|
InputCapabilitiesEditor,
|
|
1127
1252
|
{
|
|
1128
1253
|
values: capabilities.values,
|
|
@@ -1165,9 +1290,6 @@ function memoEffective(entry) {
|
|
|
1165
1290
|
}
|
|
1166
1291
|
export {
|
|
1167
1292
|
ModelSettingsPanel,
|
|
1168
|
-
SettingRowFrame,
|
|
1169
|
-
RowLabel as SettingRowLabel,
|
|
1170
|
-
formatSettingValue,
|
|
1171
1293
|
useEffectiveSettings,
|
|
1172
1294
|
useSettingsEntry,
|
|
1173
1295
|
useSettingsSelector
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/agents",
|
|
3
|
-
"version": "0.59.
|
|
3
|
+
"version": "0.59.234",
|
|
4
4
|
"description": "Portable AI Matrx agent stream protocol, event projection, and safe result-presentation primitives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -508,15 +508,15 @@
|
|
|
508
508
|
},
|
|
509
509
|
"sideEffects": false,
|
|
510
510
|
"dependencies": {
|
|
511
|
-
"@ai-matrx/alchemy": "latest",
|
|
512
511
|
"@ai-matrx/api": "latest",
|
|
513
|
-
"@ai-matrx/associations": "latest",
|
|
514
512
|
"@ai-matrx/data": "latest",
|
|
515
|
-
"@ai-matrx/design-system": "latest",
|
|
516
513
|
"@ai-matrx/content-ir": "latest",
|
|
514
|
+
"@ai-matrx/design-system": "latest",
|
|
515
|
+
"@ai-matrx/associations": "latest",
|
|
516
|
+
"@ai-matrx/alchemy": "latest",
|
|
517
|
+
"@ai-matrx/icons": "latest",
|
|
517
518
|
"@ai-matrx/diff": "latest",
|
|
518
|
-
"@ai-matrx/kit": "latest"
|
|
519
|
-
"@ai-matrx/icons": "latest"
|
|
519
|
+
"@ai-matrx/kit": "latest"
|
|
520
520
|
},
|
|
521
521
|
"peerDependencies": {
|
|
522
522
|
"react": ">=18.0.0",
|
|
@@ -561,5 +561,5 @@
|
|
|
561
561
|
"verify:tarball": "node ./scripts/verify-tarball.mjs",
|
|
562
562
|
"typegen:self-test": "node scripts/typegen/drop-guard.self-test.mjs && node scripts/typegen/check-api-types-fresh.mjs --self-test"
|
|
563
563
|
},
|
|
564
|
-
"gitHead": "
|
|
564
|
+
"gitHead": "899dceeede75f9c863ff2e80199f2bcd9c907444"
|
|
565
565
|
}
|