@ai-matrx/agents 0.59.189 → 0.59.191
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 +14 -2
- package/dist/content-transfer/index.cjs +1 -1
- package/dist/content-transfer/index.js +1 -1
- package/dist/content-transfer/react/index.cjs +1 -1
- package/dist/content-transfer/react/index.js +1 -1
- package/dist/mandates/index.cjs +4 -4
- package/dist/mandates/index.d.cts +6 -6
- package/dist/mandates/index.d.ts +6 -6
- package/dist/mandates/index.js +4 -4
- package/dist/settings/index.cjs +85 -1
- package/dist/settings/index.d.cts +159 -1
- package/dist/settings/index.d.ts +159 -1
- package/dist/settings/index.js +85 -1
- package/dist/settings/react/index.cjs +541 -157
- package/dist/settings/react/index.d.cts +208 -22
- package/dist/settings/react/index.d.ts +208 -22
- package/dist/settings/react/index.js +540 -157
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { components } from '@ai-matrx/api/types';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { JSX } from 'react';
|
|
3
|
+
import { JSX, ReactNode } from 'react';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Agent Settings — Type Definitions
|
|
@@ -166,25 +166,16 @@ interface SettingsStore {
|
|
|
166
166
|
cancelModelSwitch(agentId: string): void;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
/** The enum value that means "off" when a control declares it. */
|
|
170
|
-
declare const ENUM_OFF_VALUE = "none";
|
|
171
169
|
interface SettingControlInputProps {
|
|
172
170
|
/** Setting key (snake_case) — used for ids and response_format handling. */
|
|
173
171
|
settingKey: string;
|
|
174
|
-
explicitState?: boolean;
|
|
175
172
|
control: ControlDefinition;
|
|
176
173
|
value: unknown;
|
|
177
174
|
onChange: (value: unknown) => void;
|
|
178
175
|
disabled?: boolean;
|
|
179
176
|
id?: string;
|
|
180
|
-
/**
|
|
181
|
-
* "dense" (default) = the builder's in-row controls. "comfortable" = menu
|
|
182
|
-
* sizing for the composer's Model panel and the Chat Options window: 36px
|
|
183
|
-
* controls (44px on touch), text-sm, and a Switch for booleans.
|
|
184
|
-
*/
|
|
185
|
-
size?: "dense" | "comfortable";
|
|
186
177
|
}
|
|
187
|
-
declare function SettingControlInput({ settingKey,
|
|
178
|
+
declare function SettingControlInput({ settingKey, control, value, onChange, disabled, id, }: SettingControlInputProps): React.JSX.Element;
|
|
188
179
|
|
|
189
180
|
/**
|
|
190
181
|
* UI Gates — canonical model-gated UI flags.
|
|
@@ -229,26 +220,221 @@ declare const UI_GATE_EDITABLE_KEYS: readonly ["image_urls", "file_urls", "youtu
|
|
|
229
220
|
type UiGateEditableKey = (typeof UI_GATE_EDITABLE_KEYS)[number];
|
|
230
221
|
|
|
231
222
|
/**
|
|
232
|
-
* THE input-capabilities
|
|
233
|
-
* file URLs, YouTube)
|
|
223
|
+
* THE input-capabilities group (agent core B4): the per-agent / per-run UI gates (image URLs,
|
|
224
|
+
* file URLs, YouTube), drawn on THE model-settings panel's row frame so it lines up with the
|
|
225
|
+
* settings above it — in the builder and in every override screen alike. Controlled: the
|
|
226
|
+
* caller owns `values` and decides what a change means (the builder writes the agent's
|
|
227
|
+
* ui_gates; a conversation writes its own capability overrides, each with a reset).
|
|
234
228
|
*/
|
|
235
229
|
|
|
236
230
|
interface InputCapabilitiesEditorProps {
|
|
237
231
|
values: UiGates;
|
|
238
232
|
onChange: (key: UiGateEditableKey, value: boolean) => void;
|
|
239
|
-
|
|
240
|
-
|
|
233
|
+
/** Keys the caller changed itself; each gets a reset to what it inherits. */
|
|
234
|
+
changedKeys?: ReadonlySet<UiGateEditableKey> | undefined;
|
|
235
|
+
onReset?: ((key: UiGateEditableKey) => void) | undefined;
|
|
236
|
+
/** The reset button's words. Default "Reset to agent". */
|
|
237
|
+
resetLabel?: string | undefined;
|
|
238
|
+
/** Said under the rows when saving failed. */
|
|
239
|
+
error?: string | null | undefined;
|
|
241
240
|
idPrefix: string;
|
|
242
241
|
title?: string;
|
|
242
|
+
disabled?: boolean;
|
|
243
|
+
}
|
|
244
|
+
/** Shared builder/runtime editor for frontend-only run capabilities. */
|
|
245
|
+
declare function InputCapabilitiesEditor({ values, onChange, changedKeys, onReset, resetLabel, error, idPrefix, title, disabled, }: InputCapabilitiesEditorProps): JSX.Element;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Model Settings Catalog — the single source of truth for the STANDARD
|
|
249
|
+
* settings list, and the one chokepoint that decides which keys it contains.
|
|
250
|
+
*
|
|
251
|
+
* ── The model (two distinct surfaces) ────────────────────────────────────────
|
|
252
|
+
* 1. STANDARD list — ONLY the keys the selected model explicitly declares in
|
|
253
|
+
* its `controls` config (i.e. the parameters this model actually supports).
|
|
254
|
+
* `buildSettingsRows()` returns exactly these, grouped + ordered. Catalog
|
|
255
|
+
* keys the model does not declare are NOT shown here.
|
|
256
|
+
* 2. CAUTION surface — settings the agent has SET that the model does NOT
|
|
257
|
+
* support. These are never hidden: they are flagged as "not valid for this
|
|
258
|
+
* model" and made repairable by the validation layer (the IssueTable, fed
|
|
259
|
+
* by the `unsupported_by_model` rule). They do NOT belong in the standard
|
|
260
|
+
* list — that is exactly the "showing all possible keys" bug.
|
|
261
|
+
*
|
|
262
|
+
* The catalog exists so the standard list's labels, grouping and order live
|
|
263
|
+
* in ONE place (previously copy-pasted as `textModelSettings` /
|
|
264
|
+
* `booleanSettings` / ... into three components, each filtering by
|
|
265
|
+
* `getControl(key)` inline — which drifted and regressed). Components map over
|
|
266
|
+
* `buildSettingsRows()`; they must not filter by model themselves (ESLint
|
|
267
|
+
* enforces). The original recurring bug — set values silently dropped when a
|
|
268
|
+
* model didn't support them — is fixed by the CAUTION surface, not by dumping
|
|
269
|
+
* every key into the standard list.
|
|
270
|
+
*
|
|
271
|
+
* Guardrail: `settings-catalogue.test.ts` asserts the standard list contains
|
|
272
|
+
* ONLY supported keys (never the full catalog), and `unsupported-by-model.
|
|
273
|
+
* test.ts` asserts set-but-unsupported keys surface in the caution layer.
|
|
274
|
+
*/
|
|
275
|
+
|
|
276
|
+
type SettingsGroupId = "text" | "featureFlags" | "imageVideo" | "audio" | "other";
|
|
277
|
+
interface SettingsRow {
|
|
278
|
+
key: string;
|
|
279
|
+
label: string;
|
|
280
|
+
group: SettingsGroupId;
|
|
281
|
+
/** The model's control definition for this key. Standard rows are always
|
|
282
|
+
* supported, so this is present; typed nullable for consumer convenience. */
|
|
283
|
+
control: ControlDefinition | null;
|
|
284
|
+
/** Always true for rows returned by buildSettingsRows (standard = supported). */
|
|
285
|
+
supported: boolean;
|
|
286
|
+
/** True when the current settings hold a non-null value for this key. */
|
|
287
|
+
hasValue: boolean;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* THE SETTINGS WRITE TARGET — the one seam between THE model-settings panel
|
|
292
|
+
* (`./react/ModelSettingsPanel`) and whatever a change is written to.
|
|
293
|
+
*
|
|
294
|
+
* Owner ruling, 2026-10-21: one settings experience. The agent builder and the
|
|
295
|
+
* chat's "Model and overrides" render the SAME rows, controls, labels and
|
|
296
|
+
* order; they differ ONLY in where a change lands. The builder's target writes
|
|
297
|
+
* the agent; a conversation's (or a binding's, a mandate's, a shortcut's)
|
|
298
|
+
* target writes that record's overrides and adds a per-row reset back to what
|
|
299
|
+
* it inherits. The panel never knows which.
|
|
300
|
+
*
|
|
301
|
+
* Every method is the person's intent in the panel's words — never a store
|
|
302
|
+
* action. Optional methods are optional ACTIONS: a target that cannot bind a
|
|
303
|
+
* control to a run input simply has no `bind`, and the panel draws no button.
|
|
304
|
+
*/
|
|
305
|
+
|
|
306
|
+
/** What one row shows. Off is a `set` value the panel recognizes (setting-state). */
|
|
307
|
+
type SettingRowView =
|
|
308
|
+
/** Key absent: the model's own default applies. */
|
|
309
|
+
{
|
|
310
|
+
state: "unset";
|
|
311
|
+
modelDefault?: unknown;
|
|
312
|
+
}
|
|
313
|
+
/** A saved / effective value. */
|
|
314
|
+
| {
|
|
315
|
+
state: "set";
|
|
316
|
+
value: unknown;
|
|
317
|
+
}
|
|
318
|
+
/** The setting is a run input: its value comes from `{{variableName}}`. */
|
|
319
|
+
| {
|
|
320
|
+
state: "bound";
|
|
321
|
+
variableName: string;
|
|
322
|
+
value: unknown;
|
|
323
|
+
};
|
|
324
|
+
/** What the target knows about a row beyond its value. */
|
|
325
|
+
interface SettingRowFacts {
|
|
326
|
+
/** True when THIS target changed the row (a conversation override). */
|
|
327
|
+
changedHere?: boolean;
|
|
328
|
+
/** Where the shown value comes from, in the host's words ("Agent", "Organization"). */
|
|
329
|
+
source?: string;
|
|
330
|
+
/** The row's first validation issue, when the target validates. */
|
|
331
|
+
issue?: {
|
|
332
|
+
message: string;
|
|
333
|
+
fixable: boolean;
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
type SettingRowRead = SettingRowView & SettingRowFacts;
|
|
337
|
+
interface SettingsWriteTarget {
|
|
338
|
+
read(key: string, control: ControlDefinition | null): SettingRowRead;
|
|
339
|
+
/** The person edited the control. */
|
|
340
|
+
change(key: string, value: unknown, control: ControlDefinition | null): void;
|
|
341
|
+
/** The person ticked an unset row (store `startingValueFor`). */
|
|
342
|
+
turnOn(key: string, control: ControlDefinition): void;
|
|
343
|
+
/** The person cleared the row back to "not set". */
|
|
344
|
+
clear(key: string): void;
|
|
345
|
+
/** One-click repair of the row's issue. */
|
|
346
|
+
fix?(key: string): void;
|
|
347
|
+
/** May this row become a run input? (Builder only.) */
|
|
348
|
+
canBind?(key: string): boolean;
|
|
349
|
+
bind?(key: string, control: ControlDefinition): void;
|
|
350
|
+
unbind?(key: string, control: ControlDefinition | null): void;
|
|
351
|
+
/** Drop THIS target's change and show what it inherits again. */
|
|
352
|
+
resetToInherited?(key: string): void;
|
|
353
|
+
/** The reset button's words, in the host's noun. Default "Reset to agent". */
|
|
354
|
+
resetLabel?: string;
|
|
355
|
+
}
|
|
356
|
+
/** The frontend input capabilities (ui gates) shown under the settings groups. */
|
|
357
|
+
interface CapabilitiesWriteTarget {
|
|
358
|
+
values: UiGates;
|
|
359
|
+
change(key: UiGateEditableKey, value: boolean): void;
|
|
360
|
+
/** Keys THIS target changed; each gets its own reset. */
|
|
361
|
+
changedKeys?: ReadonlySet<UiGateEditableKey>;
|
|
362
|
+
resetToInherited?(key: UiGateEditableKey): void;
|
|
363
|
+
/** Said under the rows when saving the capabilities failed. */
|
|
364
|
+
error?: string | null;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
interface ExtraSettingRowProps {
|
|
368
|
+
rowKey: string;
|
|
369
|
+
label: string;
|
|
370
|
+
value: unknown;
|
|
243
371
|
/**
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* only, 36px rows (44px on touch), text-sm, 28px Reset when overridden.
|
|
372
|
+
* `translated`: kept as set and sent as this model's closest equivalent (the server
|
|
373
|
+
* converts it — never a warning). `unsupported`: this model has no such setting.
|
|
247
374
|
*/
|
|
248
|
-
|
|
375
|
+
kind: "translated" | "unsupported";
|
|
376
|
+
onClear: () => void;
|
|
377
|
+
/** The conversation targets' reset (drop this target's change). */
|
|
378
|
+
onReset?: (() => void) | undefined;
|
|
379
|
+
resetLabel?: string | undefined;
|
|
380
|
+
disabled?: boolean | undefined;
|
|
249
381
|
}
|
|
250
|
-
/**
|
|
251
|
-
declare function
|
|
382
|
+
/** A set value outside the model's own rows — the builder's "Translated" line, shared. */
|
|
383
|
+
declare function ExtraSettingRow({ rowKey, label, value, kind, onClear, onReset, resetLabel, disabled }: ExtraSettingRowProps): React.JSX.Element;
|
|
384
|
+
interface ModelSettingsPanelProps {
|
|
385
|
+
/** The effective model's normalized controls (`null` until a model's controls are known). */
|
|
386
|
+
controls: Record<string, unknown> | null;
|
|
387
|
+
/** The effective settings (marks `hasValue` on each catalog row). */
|
|
388
|
+
values: Record<string, unknown> | null;
|
|
389
|
+
/** Where every change lands. */
|
|
390
|
+
target: SettingsWriteTarget;
|
|
391
|
+
/** Unique per mount (ids for labels and controls). */
|
|
392
|
+
idPrefix: string;
|
|
393
|
+
/** The model picker, drawn as the panel's first row. */
|
|
394
|
+
model?: ReactNode;
|
|
395
|
+
/** Drawn between the model row and the groups: notices, the issue list, extra rows. */
|
|
396
|
+
notices?: ReactNode;
|
|
397
|
+
/** A row the host draws itself (the multi-speaker voice editor); `undefined` = the standard row. */
|
|
398
|
+
renderRow?: (row: SettingsRow) => ReactNode | undefined;
|
|
399
|
+
/** The input capabilities group, under the settings groups. */
|
|
400
|
+
capabilities?: CapabilitiesWriteTarget | undefined;
|
|
401
|
+
/** Said where the rows would be when the model declares none (or no model is chosen). */
|
|
402
|
+
emptyNote?: ReactNode;
|
|
403
|
+
disabled?: boolean;
|
|
404
|
+
}
|
|
405
|
+
declare function ModelSettingsPanel({ controls, values, target, idPrefix, model, notices, renderRow, capabilities, emptyNote, disabled, }: ModelSettingsPanelProps): React.JSX.Element;
|
|
406
|
+
|
|
407
|
+
/** A catalog value as the person reads it ("On", "auto", "1024"). */
|
|
408
|
+
declare function formatSettingValue(value: unknown): string;
|
|
409
|
+
interface SettingRowFrameProps {
|
|
410
|
+
/** `data-setting-row` — the setting key (or a host row name such as "model"). */
|
|
411
|
+
rowKey: string;
|
|
412
|
+
/** `data-setting-state` — unset | set | off | bound | translated | … */
|
|
413
|
+
state?: string;
|
|
414
|
+
/** The 16px leading column: the row's checkbox, or an icon. */
|
|
415
|
+
leading?: ReactNode;
|
|
416
|
+
label: ReactNode;
|
|
417
|
+
/** The control, or the row's value text. */
|
|
418
|
+
children?: ReactNode;
|
|
419
|
+
/** Fixed-width icons on the right: status, then actions. */
|
|
420
|
+
actions?: ReactNode;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* The one row geometry every line of the panel uses — setting rows, the model row, the
|
|
424
|
+
* translated rows, the voice row and the input capabilities — so their edges line up.
|
|
425
|
+
*/
|
|
426
|
+
declare function SettingRowFrame({ rowKey, state, leading, label, children, actions }: SettingRowFrameProps): React.JSX.Element;
|
|
427
|
+
declare function RowLabel({ htmlFor, muted, children }: {
|
|
428
|
+
htmlFor?: string;
|
|
429
|
+
muted?: boolean;
|
|
430
|
+
children: ReactNode;
|
|
431
|
+
}): React.JSX.Element;
|
|
432
|
+
/** One titled group of rows, drawn the same way for catalog groups and host groups. */
|
|
433
|
+
declare function SettingsGroupSection({ id, title, children }: {
|
|
434
|
+
id: string;
|
|
435
|
+
title?: string | undefined;
|
|
436
|
+
children: ReactNode;
|
|
437
|
+
}): React.JSX.Element;
|
|
252
438
|
|
|
253
439
|
/** Subscribe to a slice of a settings store. `select` must return a stable value for unchanged state. */
|
|
254
440
|
declare function useSettingsSelector<T>(store: SettingsStore, select: (state: AgentSettingsState) => T): T;
|
|
@@ -257,4 +443,4 @@ declare function useSettingsEntry(store: SettingsStore, agentId: string | null |
|
|
|
257
443
|
/** Defaults merged with overrides for one agent; recomputed only when the entry changes. */
|
|
258
444
|
declare function useEffectiveSettings(store: SettingsStore, agentId: string | null | undefined): Partial<AgentSettings>;
|
|
259
445
|
|
|
260
|
-
export {
|
|
446
|
+
export { ExtraSettingRow, type ExtraSettingRowProps, InputCapabilitiesEditor, type InputCapabilitiesEditorProps, ModelSettingsPanel, type ModelSettingsPanelProps, SettingControlInput, type SettingControlInputProps, SettingRowFrame, type SettingRowFrameProps, RowLabel as SettingRowLabel, SettingsGroupSection, formatSettingValue, useEffectiveSettings, useSettingsEntry, useSettingsSelector };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { components } from '@ai-matrx/api/types';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { JSX } from 'react';
|
|
3
|
+
import { JSX, ReactNode } from 'react';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Agent Settings — Type Definitions
|
|
@@ -166,25 +166,16 @@ interface SettingsStore {
|
|
|
166
166
|
cancelModelSwitch(agentId: string): void;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
/** The enum value that means "off" when a control declares it. */
|
|
170
|
-
declare const ENUM_OFF_VALUE = "none";
|
|
171
169
|
interface SettingControlInputProps {
|
|
172
170
|
/** Setting key (snake_case) — used for ids and response_format handling. */
|
|
173
171
|
settingKey: string;
|
|
174
|
-
explicitState?: boolean;
|
|
175
172
|
control: ControlDefinition;
|
|
176
173
|
value: unknown;
|
|
177
174
|
onChange: (value: unknown) => void;
|
|
178
175
|
disabled?: boolean;
|
|
179
176
|
id?: string;
|
|
180
|
-
/**
|
|
181
|
-
* "dense" (default) = the builder's in-row controls. "comfortable" = menu
|
|
182
|
-
* sizing for the composer's Model panel and the Chat Options window: 36px
|
|
183
|
-
* controls (44px on touch), text-sm, and a Switch for booleans.
|
|
184
|
-
*/
|
|
185
|
-
size?: "dense" | "comfortable";
|
|
186
177
|
}
|
|
187
|
-
declare function SettingControlInput({ settingKey,
|
|
178
|
+
declare function SettingControlInput({ settingKey, control, value, onChange, disabled, id, }: SettingControlInputProps): React.JSX.Element;
|
|
188
179
|
|
|
189
180
|
/**
|
|
190
181
|
* UI Gates — canonical model-gated UI flags.
|
|
@@ -229,26 +220,221 @@ declare const UI_GATE_EDITABLE_KEYS: readonly ["image_urls", "file_urls", "youtu
|
|
|
229
220
|
type UiGateEditableKey = (typeof UI_GATE_EDITABLE_KEYS)[number];
|
|
230
221
|
|
|
231
222
|
/**
|
|
232
|
-
* THE input-capabilities
|
|
233
|
-
* file URLs, YouTube)
|
|
223
|
+
* THE input-capabilities group (agent core B4): the per-agent / per-run UI gates (image URLs,
|
|
224
|
+
* file URLs, YouTube), drawn on THE model-settings panel's row frame so it lines up with the
|
|
225
|
+
* settings above it — in the builder and in every override screen alike. Controlled: the
|
|
226
|
+
* caller owns `values` and decides what a change means (the builder writes the agent's
|
|
227
|
+
* ui_gates; a conversation writes its own capability overrides, each with a reset).
|
|
234
228
|
*/
|
|
235
229
|
|
|
236
230
|
interface InputCapabilitiesEditorProps {
|
|
237
231
|
values: UiGates;
|
|
238
232
|
onChange: (key: UiGateEditableKey, value: boolean) => void;
|
|
239
|
-
|
|
240
|
-
|
|
233
|
+
/** Keys the caller changed itself; each gets a reset to what it inherits. */
|
|
234
|
+
changedKeys?: ReadonlySet<UiGateEditableKey> | undefined;
|
|
235
|
+
onReset?: ((key: UiGateEditableKey) => void) | undefined;
|
|
236
|
+
/** The reset button's words. Default "Reset to agent". */
|
|
237
|
+
resetLabel?: string | undefined;
|
|
238
|
+
/** Said under the rows when saving failed. */
|
|
239
|
+
error?: string | null | undefined;
|
|
241
240
|
idPrefix: string;
|
|
242
241
|
title?: string;
|
|
242
|
+
disabled?: boolean;
|
|
243
|
+
}
|
|
244
|
+
/** Shared builder/runtime editor for frontend-only run capabilities. */
|
|
245
|
+
declare function InputCapabilitiesEditor({ values, onChange, changedKeys, onReset, resetLabel, error, idPrefix, title, disabled, }: InputCapabilitiesEditorProps): JSX.Element;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Model Settings Catalog — the single source of truth for the STANDARD
|
|
249
|
+
* settings list, and the one chokepoint that decides which keys it contains.
|
|
250
|
+
*
|
|
251
|
+
* ── The model (two distinct surfaces) ────────────────────────────────────────
|
|
252
|
+
* 1. STANDARD list — ONLY the keys the selected model explicitly declares in
|
|
253
|
+
* its `controls` config (i.e. the parameters this model actually supports).
|
|
254
|
+
* `buildSettingsRows()` returns exactly these, grouped + ordered. Catalog
|
|
255
|
+
* keys the model does not declare are NOT shown here.
|
|
256
|
+
* 2. CAUTION surface — settings the agent has SET that the model does NOT
|
|
257
|
+
* support. These are never hidden: they are flagged as "not valid for this
|
|
258
|
+
* model" and made repairable by the validation layer (the IssueTable, fed
|
|
259
|
+
* by the `unsupported_by_model` rule). They do NOT belong in the standard
|
|
260
|
+
* list — that is exactly the "showing all possible keys" bug.
|
|
261
|
+
*
|
|
262
|
+
* The catalog exists so the standard list's labels, grouping and order live
|
|
263
|
+
* in ONE place (previously copy-pasted as `textModelSettings` /
|
|
264
|
+
* `booleanSettings` / ... into three components, each filtering by
|
|
265
|
+
* `getControl(key)` inline — which drifted and regressed). Components map over
|
|
266
|
+
* `buildSettingsRows()`; they must not filter by model themselves (ESLint
|
|
267
|
+
* enforces). The original recurring bug — set values silently dropped when a
|
|
268
|
+
* model didn't support them — is fixed by the CAUTION surface, not by dumping
|
|
269
|
+
* every key into the standard list.
|
|
270
|
+
*
|
|
271
|
+
* Guardrail: `settings-catalogue.test.ts` asserts the standard list contains
|
|
272
|
+
* ONLY supported keys (never the full catalog), and `unsupported-by-model.
|
|
273
|
+
* test.ts` asserts set-but-unsupported keys surface in the caution layer.
|
|
274
|
+
*/
|
|
275
|
+
|
|
276
|
+
type SettingsGroupId = "text" | "featureFlags" | "imageVideo" | "audio" | "other";
|
|
277
|
+
interface SettingsRow {
|
|
278
|
+
key: string;
|
|
279
|
+
label: string;
|
|
280
|
+
group: SettingsGroupId;
|
|
281
|
+
/** The model's control definition for this key. Standard rows are always
|
|
282
|
+
* supported, so this is present; typed nullable for consumer convenience. */
|
|
283
|
+
control: ControlDefinition | null;
|
|
284
|
+
/** Always true for rows returned by buildSettingsRows (standard = supported). */
|
|
285
|
+
supported: boolean;
|
|
286
|
+
/** True when the current settings hold a non-null value for this key. */
|
|
287
|
+
hasValue: boolean;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* THE SETTINGS WRITE TARGET — the one seam between THE model-settings panel
|
|
292
|
+
* (`./react/ModelSettingsPanel`) and whatever a change is written to.
|
|
293
|
+
*
|
|
294
|
+
* Owner ruling, 2026-10-21: one settings experience. The agent builder and the
|
|
295
|
+
* chat's "Model and overrides" render the SAME rows, controls, labels and
|
|
296
|
+
* order; they differ ONLY in where a change lands. The builder's target writes
|
|
297
|
+
* the agent; a conversation's (or a binding's, a mandate's, a shortcut's)
|
|
298
|
+
* target writes that record's overrides and adds a per-row reset back to what
|
|
299
|
+
* it inherits. The panel never knows which.
|
|
300
|
+
*
|
|
301
|
+
* Every method is the person's intent in the panel's words — never a store
|
|
302
|
+
* action. Optional methods are optional ACTIONS: a target that cannot bind a
|
|
303
|
+
* control to a run input simply has no `bind`, and the panel draws no button.
|
|
304
|
+
*/
|
|
305
|
+
|
|
306
|
+
/** What one row shows. Off is a `set` value the panel recognizes (setting-state). */
|
|
307
|
+
type SettingRowView =
|
|
308
|
+
/** Key absent: the model's own default applies. */
|
|
309
|
+
{
|
|
310
|
+
state: "unset";
|
|
311
|
+
modelDefault?: unknown;
|
|
312
|
+
}
|
|
313
|
+
/** A saved / effective value. */
|
|
314
|
+
| {
|
|
315
|
+
state: "set";
|
|
316
|
+
value: unknown;
|
|
317
|
+
}
|
|
318
|
+
/** The setting is a run input: its value comes from `{{variableName}}`. */
|
|
319
|
+
| {
|
|
320
|
+
state: "bound";
|
|
321
|
+
variableName: string;
|
|
322
|
+
value: unknown;
|
|
323
|
+
};
|
|
324
|
+
/** What the target knows about a row beyond its value. */
|
|
325
|
+
interface SettingRowFacts {
|
|
326
|
+
/** True when THIS target changed the row (a conversation override). */
|
|
327
|
+
changedHere?: boolean;
|
|
328
|
+
/** Where the shown value comes from, in the host's words ("Agent", "Organization"). */
|
|
329
|
+
source?: string;
|
|
330
|
+
/** The row's first validation issue, when the target validates. */
|
|
331
|
+
issue?: {
|
|
332
|
+
message: string;
|
|
333
|
+
fixable: boolean;
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
type SettingRowRead = SettingRowView & SettingRowFacts;
|
|
337
|
+
interface SettingsWriteTarget {
|
|
338
|
+
read(key: string, control: ControlDefinition | null): SettingRowRead;
|
|
339
|
+
/** The person edited the control. */
|
|
340
|
+
change(key: string, value: unknown, control: ControlDefinition | null): void;
|
|
341
|
+
/** The person ticked an unset row (store `startingValueFor`). */
|
|
342
|
+
turnOn(key: string, control: ControlDefinition): void;
|
|
343
|
+
/** The person cleared the row back to "not set". */
|
|
344
|
+
clear(key: string): void;
|
|
345
|
+
/** One-click repair of the row's issue. */
|
|
346
|
+
fix?(key: string): void;
|
|
347
|
+
/** May this row become a run input? (Builder only.) */
|
|
348
|
+
canBind?(key: string): boolean;
|
|
349
|
+
bind?(key: string, control: ControlDefinition): void;
|
|
350
|
+
unbind?(key: string, control: ControlDefinition | null): void;
|
|
351
|
+
/** Drop THIS target's change and show what it inherits again. */
|
|
352
|
+
resetToInherited?(key: string): void;
|
|
353
|
+
/** The reset button's words, in the host's noun. Default "Reset to agent". */
|
|
354
|
+
resetLabel?: string;
|
|
355
|
+
}
|
|
356
|
+
/** The frontend input capabilities (ui gates) shown under the settings groups. */
|
|
357
|
+
interface CapabilitiesWriteTarget {
|
|
358
|
+
values: UiGates;
|
|
359
|
+
change(key: UiGateEditableKey, value: boolean): void;
|
|
360
|
+
/** Keys THIS target changed; each gets its own reset. */
|
|
361
|
+
changedKeys?: ReadonlySet<UiGateEditableKey>;
|
|
362
|
+
resetToInherited?(key: UiGateEditableKey): void;
|
|
363
|
+
/** Said under the rows when saving the capabilities failed. */
|
|
364
|
+
error?: string | null;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
interface ExtraSettingRowProps {
|
|
368
|
+
rowKey: string;
|
|
369
|
+
label: string;
|
|
370
|
+
value: unknown;
|
|
243
371
|
/**
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* only, 36px rows (44px on touch), text-sm, 28px Reset when overridden.
|
|
372
|
+
* `translated`: kept as set and sent as this model's closest equivalent (the server
|
|
373
|
+
* converts it — never a warning). `unsupported`: this model has no such setting.
|
|
247
374
|
*/
|
|
248
|
-
|
|
375
|
+
kind: "translated" | "unsupported";
|
|
376
|
+
onClear: () => void;
|
|
377
|
+
/** The conversation targets' reset (drop this target's change). */
|
|
378
|
+
onReset?: (() => void) | undefined;
|
|
379
|
+
resetLabel?: string | undefined;
|
|
380
|
+
disabled?: boolean | undefined;
|
|
249
381
|
}
|
|
250
|
-
/**
|
|
251
|
-
declare function
|
|
382
|
+
/** A set value outside the model's own rows — the builder's "Translated" line, shared. */
|
|
383
|
+
declare function ExtraSettingRow({ rowKey, label, value, kind, onClear, onReset, resetLabel, disabled }: ExtraSettingRowProps): React.JSX.Element;
|
|
384
|
+
interface ModelSettingsPanelProps {
|
|
385
|
+
/** The effective model's normalized controls (`null` until a model's controls are known). */
|
|
386
|
+
controls: Record<string, unknown> | null;
|
|
387
|
+
/** The effective settings (marks `hasValue` on each catalog row). */
|
|
388
|
+
values: Record<string, unknown> | null;
|
|
389
|
+
/** Where every change lands. */
|
|
390
|
+
target: SettingsWriteTarget;
|
|
391
|
+
/** Unique per mount (ids for labels and controls). */
|
|
392
|
+
idPrefix: string;
|
|
393
|
+
/** The model picker, drawn as the panel's first row. */
|
|
394
|
+
model?: ReactNode;
|
|
395
|
+
/** Drawn between the model row and the groups: notices, the issue list, extra rows. */
|
|
396
|
+
notices?: ReactNode;
|
|
397
|
+
/** A row the host draws itself (the multi-speaker voice editor); `undefined` = the standard row. */
|
|
398
|
+
renderRow?: (row: SettingsRow) => ReactNode | undefined;
|
|
399
|
+
/** The input capabilities group, under the settings groups. */
|
|
400
|
+
capabilities?: CapabilitiesWriteTarget | undefined;
|
|
401
|
+
/** Said where the rows would be when the model declares none (or no model is chosen). */
|
|
402
|
+
emptyNote?: ReactNode;
|
|
403
|
+
disabled?: boolean;
|
|
404
|
+
}
|
|
405
|
+
declare function ModelSettingsPanel({ controls, values, target, idPrefix, model, notices, renderRow, capabilities, emptyNote, disabled, }: ModelSettingsPanelProps): React.JSX.Element;
|
|
406
|
+
|
|
407
|
+
/** A catalog value as the person reads it ("On", "auto", "1024"). */
|
|
408
|
+
declare function formatSettingValue(value: unknown): string;
|
|
409
|
+
interface SettingRowFrameProps {
|
|
410
|
+
/** `data-setting-row` — the setting key (or a host row name such as "model"). */
|
|
411
|
+
rowKey: string;
|
|
412
|
+
/** `data-setting-state` — unset | set | off | bound | translated | … */
|
|
413
|
+
state?: string;
|
|
414
|
+
/** The 16px leading column: the row's checkbox, or an icon. */
|
|
415
|
+
leading?: ReactNode;
|
|
416
|
+
label: ReactNode;
|
|
417
|
+
/** The control, or the row's value text. */
|
|
418
|
+
children?: ReactNode;
|
|
419
|
+
/** Fixed-width icons on the right: status, then actions. */
|
|
420
|
+
actions?: ReactNode;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* The one row geometry every line of the panel uses — setting rows, the model row, the
|
|
424
|
+
* translated rows, the voice row and the input capabilities — so their edges line up.
|
|
425
|
+
*/
|
|
426
|
+
declare function SettingRowFrame({ rowKey, state, leading, label, children, actions }: SettingRowFrameProps): React.JSX.Element;
|
|
427
|
+
declare function RowLabel({ htmlFor, muted, children }: {
|
|
428
|
+
htmlFor?: string;
|
|
429
|
+
muted?: boolean;
|
|
430
|
+
children: ReactNode;
|
|
431
|
+
}): React.JSX.Element;
|
|
432
|
+
/** One titled group of rows, drawn the same way for catalog groups and host groups. */
|
|
433
|
+
declare function SettingsGroupSection({ id, title, children }: {
|
|
434
|
+
id: string;
|
|
435
|
+
title?: string | undefined;
|
|
436
|
+
children: ReactNode;
|
|
437
|
+
}): React.JSX.Element;
|
|
252
438
|
|
|
253
439
|
/** Subscribe to a slice of a settings store. `select` must return a stable value for unchanged state. */
|
|
254
440
|
declare function useSettingsSelector<T>(store: SettingsStore, select: (state: AgentSettingsState) => T): T;
|
|
@@ -257,4 +443,4 @@ declare function useSettingsEntry(store: SettingsStore, agentId: string | null |
|
|
|
257
443
|
/** Defaults merged with overrides for one agent; recomputed only when the entry changes. */
|
|
258
444
|
declare function useEffectiveSettings(store: SettingsStore, agentId: string | null | undefined): Partial<AgentSettings>;
|
|
259
445
|
|
|
260
|
-
export {
|
|
446
|
+
export { ExtraSettingRow, type ExtraSettingRowProps, InputCapabilitiesEditor, type InputCapabilitiesEditorProps, ModelSettingsPanel, type ModelSettingsPanelProps, SettingControlInput, type SettingControlInputProps, SettingRowFrame, type SettingRowFrameProps, RowLabel as SettingRowLabel, SettingsGroupSection, formatSettingValue, useEffectiveSettings, useSettingsEntry, useSettingsSelector };
|