codex-configurator 0.2.6 → 0.2.7
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/README.md +2 -2
- package/index.js +46 -49
- package/package.json +1 -1
- package/src/components/ConfigNavigator.js +26 -4
- package/src/constants.js +1 -1
- package/src/reference/config-schema.json +140 -9
- package/src/scalarEditing.js +117 -0
- package/src/ui/commands.js +11 -7
- package/src/valuePreview.js +38 -0
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ npm start
|
|
|
39
39
|
- `↑` `↓` : move selection
|
|
40
40
|
- `PgUp` `PgDn`: move one page up/down
|
|
41
41
|
- `Home` `End`: jump to first/last item
|
|
42
|
-
- `Enter`: open selected table; for mixed scalar/object settings, choose a preset first (object presets open nested settings); for boolean settings, toggle directly; for string settings, open inline input; for other preset values, open picker
|
|
42
|
+
- `Enter`: open selected table; for mixed scalar/object settings, choose a preset first (object presets open nested settings); for boolean settings, toggle directly; for string and numeric scalar settings, open inline input; for other preset values, open picker
|
|
43
43
|
- `Del`: unset selected value or remove selected custom `<id>` entry from `config.toml`
|
|
44
44
|
- `←` / `Backspace`: move up one level (to parent table)
|
|
45
45
|
- `:`: enter command mode
|
|
@@ -49,7 +49,7 @@ npm start
|
|
|
49
49
|
- `:help`: toggle quick help overlay
|
|
50
50
|
- `:quit` (or `:q`): quit
|
|
51
51
|
|
|
52
|
-
The right-hand pane shows what each setting means,
|
|
52
|
+
The right-hand pane shows what each setting means, the current configured value for plain scalar settings, and a picker when a value has preset options.
|
|
53
53
|
Deprecated settings are marked with a `[!]` warning marker; only that marker is highlighted.
|
|
54
54
|
Model picker entries are curated presets maintained by this project.
|
|
55
55
|
In select lists, `[default]` marks the default option.
|
package/index.js
CHANGED
|
@@ -20,11 +20,13 @@ import {
|
|
|
20
20
|
writeConfig,
|
|
21
21
|
} from './src/configParser.js';
|
|
22
22
|
import { getConfigOptions, getConfigVariantMeta } from './src/configHelp.js';
|
|
23
|
-
import {
|
|
24
|
-
getReferenceOptionForPath,
|
|
25
|
-
getReferenceCustomIdPlaceholder,
|
|
26
|
-
} from './src/configReference.js';
|
|
23
|
+
import { getReferenceCustomIdPlaceholder } from './src/configReference.js';
|
|
27
24
|
import { normalizeCustomPathId } from './src/customPathId.js';
|
|
25
|
+
import {
|
|
26
|
+
getReferenceScalarType,
|
|
27
|
+
getScalarEditType,
|
|
28
|
+
parseScalarDraftValue,
|
|
29
|
+
} from './src/scalarEditing.js';
|
|
28
30
|
import {
|
|
29
31
|
applyVariantSelection,
|
|
30
32
|
buildVariantSelectorOptions,
|
|
@@ -54,17 +56,6 @@ import { StatusLine } from './src/ui/panes/StatusLine.js';
|
|
|
54
56
|
const require = createRequire(import.meta.url);
|
|
55
57
|
const { version: PACKAGE_VERSION = 'unknown' } = require('./package.json');
|
|
56
58
|
|
|
57
|
-
const isStringReferenceType = (type) =>
|
|
58
|
-
/^string(?:\s|$)/.test(String(type || '').trim());
|
|
59
|
-
|
|
60
|
-
const isStringField = (pathSegments, value) => {
|
|
61
|
-
if (typeof value === 'string') {
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return isStringReferenceType(getReferenceOptionForPath(pathSegments)?.type);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
59
|
const isCustomIdTableRow = (pathSegments, row) =>
|
|
69
60
|
row?.kind === 'table' &&
|
|
70
61
|
typeof row?.pathSegment === 'string' &&
|
|
@@ -889,13 +880,14 @@ const App = () => {
|
|
|
889
880
|
});
|
|
890
881
|
};
|
|
891
882
|
|
|
892
|
-
const
|
|
883
|
+
const beginScalarEditing = (target, targetPath, scalarType) => {
|
|
893
884
|
setEditError('');
|
|
894
885
|
setEditMode({
|
|
895
|
-
mode: '
|
|
886
|
+
mode: 'scalar',
|
|
887
|
+
scalarType,
|
|
896
888
|
path: targetPath,
|
|
897
|
-
draftValue:
|
|
898
|
-
|
|
889
|
+
draftValue:
|
|
890
|
+
typeof target.value === 'undefined' ? '' : String(target.value),
|
|
899
891
|
});
|
|
900
892
|
};
|
|
901
893
|
|
|
@@ -1028,15 +1020,24 @@ const App = () => {
|
|
|
1028
1020
|
setEditError('');
|
|
1029
1021
|
};
|
|
1030
1022
|
|
|
1031
|
-
const
|
|
1032
|
-
if (!editMode || editMode.mode !== '
|
|
1023
|
+
const applyScalarEdit = () => {
|
|
1024
|
+
if (!editMode || editMode.mode !== 'scalar') {
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
const parsedValue = parseScalarDraftValue(
|
|
1029
|
+
editMode.draftValue,
|
|
1030
|
+
editMode.scalarType,
|
|
1031
|
+
);
|
|
1032
|
+
if (!parsedValue.ok) {
|
|
1033
|
+
setEditError(parsedValue.error);
|
|
1033
1034
|
return;
|
|
1034
1035
|
}
|
|
1035
1036
|
|
|
1036
1037
|
const nextData = setValueAtPath(
|
|
1037
1038
|
snapshot.ok ? snapshot.data : {},
|
|
1038
1039
|
editMode.path,
|
|
1039
|
-
|
|
1040
|
+
parsedValue.value,
|
|
1040
1041
|
);
|
|
1041
1042
|
if (!ensureAgentConfigFile(nextData, editMode.path)) {
|
|
1042
1043
|
return;
|
|
@@ -1129,17 +1130,13 @@ const App = () => {
|
|
|
1129
1130
|
undefined,
|
|
1130
1131
|
'value',
|
|
1131
1132
|
) || [];
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1133
|
+
if (requiredOptions.length > 0) {
|
|
1134
|
+
return requiredOptions[0];
|
|
1135
|
+
}
|
|
1135
1136
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
)
|
|
1140
|
-
) {
|
|
1141
|
-
return '';
|
|
1142
|
-
}
|
|
1137
|
+
if (getReferenceScalarType(requiredPath) === 'string') {
|
|
1138
|
+
return '';
|
|
1139
|
+
}
|
|
1143
1140
|
|
|
1144
1141
|
return {};
|
|
1145
1142
|
},
|
|
@@ -1340,28 +1337,28 @@ const App = () => {
|
|
|
1340
1337
|
setCommandInput,
|
|
1341
1338
|
getCommandInput: () => commandInputRef.current,
|
|
1342
1339
|
setCommandMessage,
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1340
|
+
setEditError,
|
|
1341
|
+
beginAddIdEditing,
|
|
1342
|
+
beginScalarEditing,
|
|
1343
|
+
beginVariantEditing,
|
|
1344
|
+
beginEditing,
|
|
1345
|
+
beginFileSwitchMode,
|
|
1346
|
+
applyFileSwitch,
|
|
1347
|
+
applyScalarEdit,
|
|
1348
|
+
applyAddId,
|
|
1349
|
+
applyVariantEdit,
|
|
1350
|
+
applyEdit,
|
|
1354
1351
|
applyBooleanToggle,
|
|
1355
1352
|
unsetValueAtPath,
|
|
1356
1353
|
openPathView,
|
|
1357
1354
|
reloadActiveConfig,
|
|
1358
1355
|
getConfigOptions: getConfigOptions,
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1356
|
+
getConfigVariantMeta,
|
|
1357
|
+
getNodeAtPath,
|
|
1358
|
+
buildRows,
|
|
1359
|
+
getScalarEditType,
|
|
1360
|
+
isCustomIdTableRow,
|
|
1361
|
+
resolveMixedVariantBackNavigationPath,
|
|
1365
1362
|
adjustScrollForSelection,
|
|
1366
1363
|
getSavedIndex,
|
|
1367
1364
|
readActiveConfigSnapshot,
|
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { computePaneWidths, clamp } from '../layout.js';
|
|
11
11
|
import { getNodeAtPath, buildRows } from '../configParser.js';
|
|
12
12
|
import { filterRowsByQuery } from '../fuzzySearch.js';
|
|
13
|
+
import { getReadOnlyValuePreviewText } from '../valuePreview.js';
|
|
13
14
|
import {
|
|
14
15
|
buildVariantSelectorOptions,
|
|
15
16
|
isObjectValue,
|
|
@@ -112,7 +113,7 @@ const renderArrayDetails = (rows) => {
|
|
|
112
113
|
);
|
|
113
114
|
};
|
|
114
115
|
|
|
115
|
-
const
|
|
116
|
+
const renderScalarEditor = (draftValue, scalarType) =>
|
|
116
117
|
React.createElement(
|
|
117
118
|
React.Fragment,
|
|
118
119
|
null,
|
|
@@ -124,7 +125,13 @@ const renderTextEditor = (draftValue) =>
|
|
|
124
125
|
React.createElement(
|
|
125
126
|
Text,
|
|
126
127
|
{ color: 'gray', wrap: 'truncate-end' },
|
|
127
|
-
|
|
128
|
+
`Type ${
|
|
129
|
+
scalarType === 'string'
|
|
130
|
+
? 'text'
|
|
131
|
+
: scalarType === 'integer'
|
|
132
|
+
? 'integer'
|
|
133
|
+
: 'number'
|
|
134
|
+
} • Enter: save • Esc: cancel`,
|
|
128
135
|
),
|
|
129
136
|
);
|
|
130
137
|
|
|
@@ -416,6 +423,10 @@ export const ConfigNavigator = ({
|
|
|
416
423
|
);
|
|
417
424
|
const shouldShowReadOnlyOptions =
|
|
418
425
|
readOnlyOptions.length > 0 && !isBooleanOnlyOptions(readOnlyOptions);
|
|
426
|
+
const readOnlyValuePreviewText = getReadOnlyValuePreviewText(
|
|
427
|
+
selectedRow,
|
|
428
|
+
shouldShowReadOnlyOptions,
|
|
429
|
+
);
|
|
419
430
|
|
|
420
431
|
const editRow = rows[selected] || null;
|
|
421
432
|
const editDefaultOption =
|
|
@@ -471,8 +482,8 @@ export const ConfigNavigator = ({
|
|
|
471
482
|
)
|
|
472
483
|
: null;
|
|
473
484
|
const optionSelector = editMode
|
|
474
|
-
? editMode.mode === '
|
|
475
|
-
?
|
|
485
|
+
? editMode.mode === 'scalar'
|
|
486
|
+
? renderScalarEditor(editMode.draftValue, editMode.scalarType)
|
|
476
487
|
: editMode.mode === 'add-id'
|
|
477
488
|
? renderIdEditor(editMode.placeholder, editMode.draftValue)
|
|
478
489
|
: renderEditableOptions(
|
|
@@ -497,6 +508,17 @@ export const ConfigNavigator = ({
|
|
|
497
508
|
false,
|
|
498
509
|
),
|
|
499
510
|
)
|
|
511
|
+
: readOnlyValuePreviewText
|
|
512
|
+
? React.createElement(
|
|
513
|
+
React.Fragment,
|
|
514
|
+
null,
|
|
515
|
+
React.createElement(Text, { color: 'gray' }, ' '),
|
|
516
|
+
React.createElement(
|
|
517
|
+
Text,
|
|
518
|
+
{ color: 'white', wrap: 'truncate-end' },
|
|
519
|
+
readOnlyValuePreviewText,
|
|
520
|
+
),
|
|
521
|
+
)
|
|
500
522
|
: selectedRow?.kind === 'array'
|
|
501
523
|
? renderArrayDetails(selectedRow.value)
|
|
502
524
|
: null;
|
package/src/constants.js
CHANGED
|
@@ -3,7 +3,7 @@ export const CONTROL_HINT =
|
|
|
3
3
|
export const FILE_SWITCH_HINT =
|
|
4
4
|
'↑/↓ choose • PgUp/PgDn page • Home/End jump • Enter switch file • Esc/Backspace/← cancel';
|
|
5
5
|
export const EDIT_CONTROL_HINT =
|
|
6
|
-
'↑/↓ choose • PgUp/PgDn page • Home/End jump • Enter save • Esc/Backspace/← cancel • Del delete char (
|
|
6
|
+
'↑/↓ choose • PgUp/PgDn page • Home/End jump • Enter save • Esc/Backspace/← cancel • Del delete char (inline input)';
|
|
7
7
|
export const FILTER_CONTROL_HINT =
|
|
8
8
|
'Type filter • Enter/Esc: done • Del/Backspace: delete • Ctrl+U: clear';
|
|
9
9
|
export const COMMAND_HINT = 'Type : to see commands';
|
|
@@ -20,6 +20,13 @@
|
|
|
20
20
|
"description": {
|
|
21
21
|
"description": "Human-facing role documentation used in spawn tool guidance.",
|
|
22
22
|
"type": "string"
|
|
23
|
+
},
|
|
24
|
+
"nickname_candidates": {
|
|
25
|
+
"description": "Candidate nicknames for agents spawned with this role.",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
},
|
|
29
|
+
"type": "array"
|
|
23
30
|
}
|
|
24
31
|
},
|
|
25
32
|
"type": "object"
|
|
@@ -313,6 +320,9 @@
|
|
|
313
320
|
"apps_mcp_gateway": {
|
|
314
321
|
"type": "boolean"
|
|
315
322
|
},
|
|
323
|
+
"artifact": {
|
|
324
|
+
"type": "boolean"
|
|
325
|
+
},
|
|
316
326
|
"child_agents_md": {
|
|
317
327
|
"type": "boolean"
|
|
318
328
|
},
|
|
@@ -349,6 +359,15 @@
|
|
|
349
359
|
"experimental_windows_sandbox": {
|
|
350
360
|
"type": "boolean"
|
|
351
361
|
},
|
|
362
|
+
"fast_mode": {
|
|
363
|
+
"type": "boolean"
|
|
364
|
+
},
|
|
365
|
+
"image_detail_original": {
|
|
366
|
+
"type": "boolean"
|
|
367
|
+
},
|
|
368
|
+
"image_generation": {
|
|
369
|
+
"type": "boolean"
|
|
370
|
+
},
|
|
352
371
|
"include_apply_patch_tool": {
|
|
353
372
|
"type": "boolean"
|
|
354
373
|
},
|
|
@@ -370,6 +389,9 @@
|
|
|
370
389
|
"personality": {
|
|
371
390
|
"type": "boolean"
|
|
372
391
|
},
|
|
392
|
+
"plugins": {
|
|
393
|
+
"type": "boolean"
|
|
394
|
+
},
|
|
373
395
|
"powershell_utf8": {
|
|
374
396
|
"type": "boolean"
|
|
375
397
|
},
|
|
@@ -502,6 +524,9 @@
|
|
|
502
524
|
"sandbox_mode": {
|
|
503
525
|
"$ref": "#/definitions/SandboxMode"
|
|
504
526
|
},
|
|
527
|
+
"service_tier": {
|
|
528
|
+
"$ref": "#/definitions/ServiceTier"
|
|
529
|
+
},
|
|
505
530
|
"tools_view_image": {
|
|
506
531
|
"type": "boolean"
|
|
507
532
|
},
|
|
@@ -613,7 +638,19 @@
|
|
|
613
638
|
"additionalProperties": false,
|
|
614
639
|
"description": "Memories settings loaded from config.toml.",
|
|
615
640
|
"properties": {
|
|
616
|
-
"
|
|
641
|
+
"consolidation_model": {
|
|
642
|
+
"description": "Model used for memory consolidation.",
|
|
643
|
+
"type": "string"
|
|
644
|
+
},
|
|
645
|
+
"extract_model": {
|
|
646
|
+
"description": "Model used for thread summarisation.",
|
|
647
|
+
"type": "string"
|
|
648
|
+
},
|
|
649
|
+
"generate_memories": {
|
|
650
|
+
"description": "When `false`, newly created threads are stored with `memory_mode = \"disabled\"` in the state DB.",
|
|
651
|
+
"type": "boolean"
|
|
652
|
+
},
|
|
653
|
+
"max_raw_memories_for_consolidation": {
|
|
617
654
|
"description": "Maximum number of recent raw memories retained for global consolidation.",
|
|
618
655
|
"format": "uint",
|
|
619
656
|
"minimum": 0,
|
|
@@ -640,17 +677,25 @@
|
|
|
640
677
|
"format": "int64",
|
|
641
678
|
"type": "integer"
|
|
642
679
|
},
|
|
643
|
-
"
|
|
644
|
-
"description": "
|
|
645
|
-
"type": "
|
|
680
|
+
"no_memories_if_mcp_or_web_search": {
|
|
681
|
+
"description": "When `true`, web searches and MCP tool calls mark the thread `memory_mode` as `\"polluted\"`.",
|
|
682
|
+
"type": "boolean"
|
|
646
683
|
},
|
|
647
|
-
"
|
|
648
|
-
"description": "
|
|
649
|
-
"type": "
|
|
684
|
+
"use_memories": {
|
|
685
|
+
"description": "When `false`, skip injecting memory usage instructions into developer prompts.",
|
|
686
|
+
"type": "boolean"
|
|
650
687
|
}
|
|
651
688
|
},
|
|
652
689
|
"type": "object"
|
|
653
690
|
},
|
|
691
|
+
"ModelAvailabilityNuxConfig": {
|
|
692
|
+
"additionalProperties": {
|
|
693
|
+
"format": "uint32",
|
|
694
|
+
"minimum": 0,
|
|
695
|
+
"type": "integer"
|
|
696
|
+
},
|
|
697
|
+
"type": "object"
|
|
698
|
+
},
|
|
654
699
|
"ModelProviderInfo": {
|
|
655
700
|
"additionalProperties": false,
|
|
656
701
|
"description": "Serializable representation of a provider definition.",
|
|
@@ -1069,6 +1114,16 @@
|
|
|
1069
1114
|
],
|
|
1070
1115
|
"type": "string"
|
|
1071
1116
|
},
|
|
1117
|
+
"PluginConfig": {
|
|
1118
|
+
"additionalProperties": false,
|
|
1119
|
+
"properties": {
|
|
1120
|
+
"enabled": {
|
|
1121
|
+
"default": true,
|
|
1122
|
+
"type": "boolean"
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
"type": "object"
|
|
1126
|
+
},
|
|
1072
1127
|
"ProjectConfig": {
|
|
1073
1128
|
"additionalProperties": false,
|
|
1074
1129
|
"properties": {
|
|
@@ -1146,6 +1201,10 @@
|
|
|
1146
1201
|
},
|
|
1147
1202
|
"type": "object"
|
|
1148
1203
|
},
|
|
1204
|
+
"oauth_resource": {
|
|
1205
|
+
"default": null,
|
|
1206
|
+
"type": "string"
|
|
1207
|
+
},
|
|
1149
1208
|
"required": {
|
|
1150
1209
|
"default": null,
|
|
1151
1210
|
"type": "boolean"
|
|
@@ -1179,6 +1238,18 @@
|
|
|
1179
1238
|
},
|
|
1180
1239
|
"type": "object"
|
|
1181
1240
|
},
|
|
1241
|
+
"RealtimeAudioToml": {
|
|
1242
|
+
"additionalProperties": false,
|
|
1243
|
+
"properties": {
|
|
1244
|
+
"microphone": {
|
|
1245
|
+
"type": "string"
|
|
1246
|
+
},
|
|
1247
|
+
"speaker": {
|
|
1248
|
+
"type": "string"
|
|
1249
|
+
}
|
|
1250
|
+
},
|
|
1251
|
+
"type": "object"
|
|
1252
|
+
},
|
|
1182
1253
|
"ReasoningEffort": {
|
|
1183
1254
|
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
|
1184
1255
|
"enum": [
|
|
@@ -1266,6 +1337,13 @@
|
|
|
1266
1337
|
},
|
|
1267
1338
|
"type": "object"
|
|
1268
1339
|
},
|
|
1340
|
+
"ServiceTier": {
|
|
1341
|
+
"enum": [
|
|
1342
|
+
"fast",
|
|
1343
|
+
"flex"
|
|
1344
|
+
],
|
|
1345
|
+
"type": "string"
|
|
1346
|
+
},
|
|
1269
1347
|
"ShellEnvironmentPolicyInherit": {
|
|
1270
1348
|
"oneOf": [
|
|
1271
1349
|
{
|
|
@@ -1396,6 +1474,15 @@
|
|
|
1396
1474
|
"description": "Enable animations (welcome screen, shimmer effects, spinners). Defaults to `true`.",
|
|
1397
1475
|
"type": "boolean"
|
|
1398
1476
|
},
|
|
1477
|
+
"model_availability_nux": {
|
|
1478
|
+
"allOf": [
|
|
1479
|
+
{
|
|
1480
|
+
"$ref": "#/definitions/ModelAvailabilityNuxConfig"
|
|
1481
|
+
}
|
|
1482
|
+
],
|
|
1483
|
+
"default": {},
|
|
1484
|
+
"description": "Startup tooltip availability NUX state persisted by the TUI."
|
|
1485
|
+
},
|
|
1399
1486
|
"notification_method": {
|
|
1400
1487
|
"allOf": [
|
|
1401
1488
|
{
|
|
@@ -1540,6 +1627,15 @@
|
|
|
1540
1627
|
"default": null,
|
|
1541
1628
|
"description": "Settings for app-specific controls."
|
|
1542
1629
|
},
|
|
1630
|
+
"audio": {
|
|
1631
|
+
"allOf": [
|
|
1632
|
+
{
|
|
1633
|
+
"$ref": "#/definitions/RealtimeAudioToml"
|
|
1634
|
+
}
|
|
1635
|
+
],
|
|
1636
|
+
"default": null,
|
|
1637
|
+
"description": "Machine-local realtime audio device preferences used by realtime voice."
|
|
1638
|
+
},
|
|
1543
1639
|
"background_terminal_max_timeout": {
|
|
1544
1640
|
"description": "Maximum poll window for background terminal output (`write_stdin`), in milliseconds. Default: `300000` (5 minutes).",
|
|
1545
1641
|
"format": "uint64",
|
|
@@ -1584,11 +1680,15 @@
|
|
|
1584
1680
|
"$ref": "#/definitions/AbsolutePathBuf"
|
|
1585
1681
|
},
|
|
1586
1682
|
"experimental_realtime_ws_backend_prompt": {
|
|
1587
|
-
"description": "Experimental / do not use. Overrides only the realtime conversation websocket transport
|
|
1683
|
+
"description": "Experimental / do not use. Overrides only the realtime conversation websocket transport instructions (the `Op::RealtimeConversation` `/ws` session.update instructions) without changing normal prompts.",
|
|
1588
1684
|
"type": "string"
|
|
1589
1685
|
},
|
|
1590
1686
|
"experimental_realtime_ws_base_url": {
|
|
1591
|
-
"description": "Experimental / do not use. Overrides only the realtime conversation websocket transport base URL (the `Op::RealtimeConversation` `/
|
|
1687
|
+
"description": "Experimental / do not use. Overrides only the realtime conversation websocket transport base URL (the `Op::RealtimeConversation` `/v1/realtime` connection) without changing normal provider HTTP requests.",
|
|
1688
|
+
"type": "string"
|
|
1689
|
+
},
|
|
1690
|
+
"experimental_realtime_ws_model": {
|
|
1691
|
+
"description": "Experimental / do not use. Selects the realtime websocket model/snapshot used for the `Op::RealtimeConversation` connection.",
|
|
1592
1692
|
"type": "string"
|
|
1593
1693
|
},
|
|
1594
1694
|
"experimental_use_freeform_apply_patch": {
|
|
@@ -1611,6 +1711,9 @@
|
|
|
1611
1711
|
"apps_mcp_gateway": {
|
|
1612
1712
|
"type": "boolean"
|
|
1613
1713
|
},
|
|
1714
|
+
"artifact": {
|
|
1715
|
+
"type": "boolean"
|
|
1716
|
+
},
|
|
1614
1717
|
"child_agents_md": {
|
|
1615
1718
|
"type": "boolean"
|
|
1616
1719
|
},
|
|
@@ -1647,6 +1750,15 @@
|
|
|
1647
1750
|
"experimental_windows_sandbox": {
|
|
1648
1751
|
"type": "boolean"
|
|
1649
1752
|
},
|
|
1753
|
+
"fast_mode": {
|
|
1754
|
+
"type": "boolean"
|
|
1755
|
+
},
|
|
1756
|
+
"image_detail_original": {
|
|
1757
|
+
"type": "boolean"
|
|
1758
|
+
},
|
|
1759
|
+
"image_generation": {
|
|
1760
|
+
"type": "boolean"
|
|
1761
|
+
},
|
|
1650
1762
|
"include_apply_patch_tool": {
|
|
1651
1763
|
"type": "boolean"
|
|
1652
1764
|
},
|
|
@@ -1668,6 +1780,9 @@
|
|
|
1668
1780
|
"personality": {
|
|
1669
1781
|
"type": "boolean"
|
|
1670
1782
|
},
|
|
1783
|
+
"plugins": {
|
|
1784
|
+
"type": "boolean"
|
|
1785
|
+
},
|
|
1671
1786
|
"powershell_utf8": {
|
|
1672
1787
|
"type": "boolean"
|
|
1673
1788
|
},
|
|
@@ -1965,6 +2080,14 @@
|
|
|
1965
2080
|
"plan_mode_reasoning_effort": {
|
|
1966
2081
|
"$ref": "#/definitions/ReasoningEffort"
|
|
1967
2082
|
},
|
|
2083
|
+
"plugins": {
|
|
2084
|
+
"additionalProperties": {
|
|
2085
|
+
"$ref": "#/definitions/PluginConfig"
|
|
2086
|
+
},
|
|
2087
|
+
"default": {},
|
|
2088
|
+
"description": "User-level plugin config entries keyed by plugin name.",
|
|
2089
|
+
"type": "object"
|
|
2090
|
+
},
|
|
1968
2091
|
"profile": {
|
|
1969
2092
|
"description": "Profile to use from the `profiles` map.",
|
|
1970
2093
|
"type": "string"
|
|
@@ -2024,6 +2147,14 @@
|
|
|
2024
2147
|
],
|
|
2025
2148
|
"description": "Sandbox configuration to apply if `sandbox` is `WorkspaceWrite`."
|
|
2026
2149
|
},
|
|
2150
|
+
"service_tier": {
|
|
2151
|
+
"allOf": [
|
|
2152
|
+
{
|
|
2153
|
+
"$ref": "#/definitions/ServiceTier"
|
|
2154
|
+
}
|
|
2155
|
+
],
|
|
2156
|
+
"description": "Optional explicit service tier preference for new turns (`fast` or `flex`)."
|
|
2157
|
+
},
|
|
2027
2158
|
"shell_environment_policy": {
|
|
2028
2159
|
"allOf": [
|
|
2029
2160
|
{
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { getReferenceOptionForPath } from './configReference.js';
|
|
2
|
+
|
|
3
|
+
const STRING_REFERENCE_TYPE_PATTERN = /^string(?:\s|$)/;
|
|
4
|
+
const DIGIT_GROUP_PATTERN = '\\d(?:_?\\d)*';
|
|
5
|
+
const INTEGER_DRAFT_PATTERN = new RegExp(
|
|
6
|
+
`^[+-]?${DIGIT_GROUP_PATTERN}$`,
|
|
7
|
+
);
|
|
8
|
+
const NUMBER_DRAFT_PATTERN = new RegExp(
|
|
9
|
+
`^[+-]?(?:(?:${DIGIT_GROUP_PATTERN}(?:\\.(?:${DIGIT_GROUP_PATTERN})?)?)|(?:\\.${DIGIT_GROUP_PATTERN}))(?:[eE][+-]?${DIGIT_GROUP_PATTERN})?$`,
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
export const getReferenceScalarType = (pathSegments) => {
|
|
13
|
+
const referenceType = String(
|
|
14
|
+
getReferenceOptionForPath(pathSegments)?.type || '',
|
|
15
|
+
).trim();
|
|
16
|
+
|
|
17
|
+
if (STRING_REFERENCE_TYPE_PATTERN.test(referenceType)) {
|
|
18
|
+
return 'string';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (referenceType === 'integer') {
|
|
22
|
+
return 'integer';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (referenceType === 'number') {
|
|
26
|
+
return 'number';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return null;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getScalarEditType = (pathSegments, value) => {
|
|
33
|
+
const referenceScalarType = getReferenceScalarType(pathSegments);
|
|
34
|
+
if (referenceScalarType) {
|
|
35
|
+
return referenceScalarType;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (typeof value === 'string') {
|
|
39
|
+
return 'string';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (typeof value === 'number') {
|
|
43
|
+
return Number.isInteger(value) ? 'integer' : 'number';
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const parseScalarDraftValue = (draftValue, scalarType) => {
|
|
49
|
+
const nextDraftValue =
|
|
50
|
+
typeof draftValue === 'string'
|
|
51
|
+
? draftValue
|
|
52
|
+
: String(draftValue ?? '');
|
|
53
|
+
|
|
54
|
+
if (scalarType === 'string') {
|
|
55
|
+
return {
|
|
56
|
+
ok: true,
|
|
57
|
+
value: nextDraftValue,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const normalized = nextDraftValue.trim();
|
|
62
|
+
if (!normalized) {
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
error: 'Value cannot be empty. Use Del to unset it.',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (scalarType === 'integer') {
|
|
70
|
+
if (!INTEGER_DRAFT_PATTERN.test(normalized)) {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
error: 'Value must be a whole number.',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const parsed = Number(normalized.replaceAll('_', ''));
|
|
78
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
error: 'Value must be a safe integer.',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
ok: true,
|
|
87
|
+
value: parsed,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (scalarType === 'number') {
|
|
92
|
+
if (!NUMBER_DRAFT_PATTERN.test(normalized)) {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
error: 'Value must be a finite decimal number.',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const parsed = Number(normalized.replaceAll('_', ''));
|
|
100
|
+
if (!Number.isFinite(parsed)) {
|
|
101
|
+
return {
|
|
102
|
+
ok: false,
|
|
103
|
+
error: 'Value must be a finite decimal number.',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
ok: true,
|
|
109
|
+
value: parsed,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
error: 'Unsupported scalar type.',
|
|
116
|
+
};
|
|
117
|
+
};
|
package/src/ui/commands.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
FILTER_CONTROL_HINT,
|
|
16
16
|
} from '../constants.js';
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const isInlineDraftMode = (mode) => mode === 'scalar' || mode === 'add-id';
|
|
19
19
|
|
|
20
20
|
const isBooleanOnlyOptions = (options) =>
|
|
21
21
|
Array.isArray(options) &&
|
|
@@ -215,7 +215,7 @@ export const executeInputCommand = ({ input, key, context }) => {
|
|
|
215
215
|
configFileCatalog,
|
|
216
216
|
} = context;
|
|
217
217
|
|
|
218
|
-
const
|
|
218
|
+
const isInlineEditing = isInlineDraftMode(editMode?.mode);
|
|
219
219
|
const isCapturingCommand = isCommandModeLocked || isCommandMode;
|
|
220
220
|
|
|
221
221
|
if (isCapturingCommand) {
|
|
@@ -382,10 +382,10 @@ export const executeInputCommand = ({ input, key, context }) => {
|
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
if (editMode) {
|
|
385
|
-
if (
|
|
385
|
+
if (isInlineEditing) {
|
|
386
386
|
if (key.return) {
|
|
387
|
-
if (editMode.mode === '
|
|
388
|
-
context.
|
|
387
|
+
if (editMode.mode === 'scalar') {
|
|
388
|
+
context.applyScalarEdit();
|
|
389
389
|
return true;
|
|
390
390
|
}
|
|
391
391
|
|
|
@@ -669,8 +669,12 @@ export const executeInputCommand = ({ input, key, context }) => {
|
|
|
669
669
|
return true;
|
|
670
670
|
}
|
|
671
671
|
|
|
672
|
-
|
|
673
|
-
|
|
672
|
+
const scalarType = context.getScalarEditType(
|
|
673
|
+
targetPath,
|
|
674
|
+
target.value,
|
|
675
|
+
);
|
|
676
|
+
if (scalarType) {
|
|
677
|
+
context.beginScalarEditing(target, targetPath, scalarType);
|
|
674
678
|
}
|
|
675
679
|
|
|
676
680
|
return true;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const isPrimitivePreviewValue = (value) =>
|
|
2
|
+
value === null ||
|
|
3
|
+
typeof value === 'string' ||
|
|
4
|
+
typeof value === 'number' ||
|
|
5
|
+
typeof value === 'boolean';
|
|
6
|
+
|
|
7
|
+
export const formatReadOnlyValuePreview = (value) => {
|
|
8
|
+
if (typeof value === 'string') {
|
|
9
|
+
return JSON.stringify(value);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (
|
|
13
|
+
typeof value === 'number' ||
|
|
14
|
+
typeof value === 'boolean' ||
|
|
15
|
+
value === null
|
|
16
|
+
) {
|
|
17
|
+
return String(value);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return String(value);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const getReadOnlyValuePreviewText = (
|
|
24
|
+
row,
|
|
25
|
+
shouldShowReadOnlyOptions = false,
|
|
26
|
+
) => {
|
|
27
|
+
if (
|
|
28
|
+
!row ||
|
|
29
|
+
row.kind !== 'value' ||
|
|
30
|
+
row.isConfigured !== true ||
|
|
31
|
+
shouldShowReadOnlyOptions ||
|
|
32
|
+
!isPrimitivePreviewValue(row.value)
|
|
33
|
+
) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return `Current: ${formatReadOnlyValuePreview(row.value)}`;
|
|
38
|
+
};
|