@lesliechan721/aw 0.1.0-beta.37 → 0.1.0-beta.39
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/dist/authoring/assets/aw-runtime-config.d.mts +13 -0
- package/dist/authoring/assets/aw-runtime-config.mjs +199 -0
- package/dist/authoring/assets/aw-runtime-config.mjs.map +1 -0
- package/dist/authoring/scripts/lib/plugin-version-check.mjs +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +44 -3
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
- package/dist/scripts/test-plugin-scripts.js +3 -0
- package/dist/scripts/test-plugin-scripts.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +1 -1
- package/dist/src/commands/aw-capabilities.js +4 -0
- package/dist/src/commands/aw-capabilities.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +4 -0
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-integration.js +16 -11
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/skill-eval.d.ts +1 -0
- package/dist/src/commands/skill-eval.js +14 -2
- package/dist/src/commands/skill-eval.js.map +1 -1
- package/dist/src/generators/local-plugin.js +3 -0
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/review/review-profile.js +55 -15
- package/dist/src/review/review-profile.js.map +1 -1
- package/dist/src/review/source-binding.d.ts +3 -2
- package/dist/src/review/source-binding.js +32 -6
- package/dist/src/review/source-binding.js.map +1 -1
- package/dist/src/tui/config-leaf-editor.d.ts +16 -0
- package/dist/src/tui/config-leaf-editor.js +206 -0
- package/dist/src/tui/config-leaf-editor.js.map +1 -0
- package/dist/src/tui/config-value-presentation.js +23 -12
- package/dist/src/tui/config-value-presentation.js.map +1 -1
- package/dist/src/tui/console-app-v4.js +137 -25
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/model.js +12 -12
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/utils/artifact-renderer.d.ts +4 -0
- package/dist/src/utils/artifact-renderer.js +24 -3
- package/dist/src/utils/artifact-renderer.js.map +1 -1
- package/dist/src/utils/artifact-request.js +1 -5
- package/dist/src/utils/artifact-request.js.map +1 -1
- package/dist/src/utils/bundle-layout.js +8 -0
- package/dist/src/utils/bundle-layout.js.map +1 -1
- package/dist/src/utils/plugin-config-write.js +11 -1
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +13 -0
- package/dist/src/utils/plugin-config.js +113 -3
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/dist/src/utils/plugin-scripts.d.ts +3 -0
- package/dist/src/utils/plugin-scripts.js +18 -3
- package/dist/src/utils/plugin-scripts.js.map +1 -1
- package/dist/src/utils/runtime-config.d.ts +20 -0
- package/dist/src/utils/runtime-config.js +75 -0
- package/dist/src/utils/runtime-config.js.map +1 -0
- package/package.json +3 -3
|
@@ -2,10 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { arrayDraftChanged, arrayDraftValue, createConfigArrayDraft, editConfigArrayDraft } from './config-array-draft.js';
|
|
3
3
|
import { PLUGIN_CONFIG_ARRAY_MAX_ITEMS } from '@lesliechan721/aw-plugin-core';
|
|
4
4
|
import { presentConfigValue, safeConfigText } from './config-value-presentation.js';
|
|
5
|
+
import { ConfigLeafEditor } from './config-leaf-editor.js';
|
|
5
6
|
import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
6
7
|
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
7
8
|
import path from 'node:path';
|
|
8
|
-
import { validatePluginConfigValue, } from '@lesliechan721/aw-plugin-core/manifest';
|
|
9
|
+
import { resolvePluginConfigObjectProperties, validatePluginConfigValue, } from '@lesliechan721/aw-plugin-core/manifest';
|
|
9
10
|
import { CATALOG_BETA_REF, CATALOG_LATEST_REF, OFFICIAL_CATALOG_SOURCE_SSH_URL, OFFICIAL_CATALOG_SOURCE_URL, } from '../constants.js';
|
|
10
11
|
import { CATALOG_SOURCE_ID_PATTERN } from '../utils/catalog-sources.js';
|
|
11
12
|
import { canonicalizeCatalogGitUrl } from '../utils/catalog-source-identity.js';
|
|
@@ -1019,6 +1020,8 @@ export function ConsoleAppV4(props) {
|
|
|
1019
1020
|
const [objectDrafts, setObjectDrafts] = useState({});
|
|
1020
1021
|
const [changedObjectDraftKeys, setChangedObjectDraftKeys] = useState([]);
|
|
1021
1022
|
const [objectError, setObjectError] = useState();
|
|
1023
|
+
const [nestedPropertyRevision, setNestedPropertyRevision] = useState();
|
|
1024
|
+
const [objectVariantPreview, setObjectVariantPreview] = useState();
|
|
1022
1025
|
const [inputValue, setInputValue] = useState('');
|
|
1023
1026
|
const [inputError, setInputError] = useState();
|
|
1024
1027
|
const [configActionError, setConfigActionError] = useState();
|
|
@@ -1064,7 +1067,7 @@ export function ConsoleAppV4(props) {
|
|
|
1064
1067
|
const dependencyGraphContexts = useRef(new Map());
|
|
1065
1068
|
const externalDraftRevision = useRef({ config: 0, source: 0, batch: 0 });
|
|
1066
1069
|
const previousExternalDraftValues = useRef({
|
|
1067
|
-
configDrafts, configCandidate, arrayDrafts, objectDrafts, changedObjectDraftKeys, sourceDraft, batchDraft,
|
|
1070
|
+
configDrafts, configCandidate, arrayDrafts, objectDrafts, changedObjectDraftKeys, nestedPropertyRevision, objectVariantPreview, sourceDraft, batchDraft,
|
|
1068
1071
|
});
|
|
1069
1072
|
const externalDraftFlowIds = useRef(new Map());
|
|
1070
1073
|
const configOverviewAnchors = useRef(new Map());
|
|
@@ -1358,7 +1361,9 @@ export function ConsoleAppV4(props) {
|
|
|
1358
1361
|
|| previous.configCandidate !== configCandidate
|
|
1359
1362
|
|| previous.arrayDrafts !== arrayDrafts
|
|
1360
1363
|
|| previous.objectDrafts !== objectDrafts
|
|
1361
|
-
|| previous.changedObjectDraftKeys !== changedObjectDraftKeys
|
|
1364
|
+
|| previous.changedObjectDraftKeys !== changedObjectDraftKeys
|
|
1365
|
+
|| previous.nestedPropertyRevision !== nestedPropertyRevision
|
|
1366
|
+
|| previous.objectVariantPreview !== objectVariantPreview) {
|
|
1362
1367
|
externalDraftRevision.current.config += 1;
|
|
1363
1368
|
}
|
|
1364
1369
|
if (previous.sourceDraft !== sourceDraft)
|
|
@@ -1366,7 +1371,7 @@ export function ConsoleAppV4(props) {
|
|
|
1366
1371
|
if (previous.batchDraft !== batchDraft)
|
|
1367
1372
|
externalDraftRevision.current.batch += 1;
|
|
1368
1373
|
previousExternalDraftValues.current = {
|
|
1369
|
-
configDrafts, configCandidate, arrayDrafts, objectDrafts, changedObjectDraftKeys, sourceDraft, batchDraft,
|
|
1374
|
+
configDrafts, configCandidate, arrayDrafts, objectDrafts, changedObjectDraftKeys, nestedPropertyRevision, objectVariantPreview, sourceDraft, batchDraft,
|
|
1370
1375
|
};
|
|
1371
1376
|
const currentFlowId = snapshot.router.currentFlowId;
|
|
1372
1377
|
if (currentFlowId && configRouteOwner) {
|
|
@@ -1375,7 +1380,7 @@ export function ConsoleAppV4(props) {
|
|
|
1375
1380
|
if (currentFlowId && sourceDraft)
|
|
1376
1381
|
externalDraftFlowIds.current.set(sourceDraft.owner, currentFlowId);
|
|
1377
1382
|
const drafts = [];
|
|
1378
|
-
if ((dirty || configCandidate || Object.values(arrayDrafts).some((draft) => draft.initial === undefined ? draft.rows.length > 0 : arrayDraftChanged(draft)) || changedObjectDraftKeys.length > 0) && draftOwner) {
|
|
1383
|
+
if ((dirty || configCandidate || nestedPropertyRevision || objectVariantPreview || Object.values(arrayDrafts).some((draft) => draft.initial === undefined ? draft.rows.length > 0 : arrayDraftChanged(draft)) || changedObjectDraftKeys.length > 0) && draftOwner) {
|
|
1379
1384
|
const flowId = externalDraftFlowIds.current.get(draftOwner);
|
|
1380
1385
|
drafts.push({
|
|
1381
1386
|
kind: 'configDraft', owner: draftOwner, revision: externalDraftRevision.current.config,
|
|
@@ -1398,7 +1403,7 @@ export function ConsoleAppV4(props) {
|
|
|
1398
1403
|
props.controller.setExternalDraftState(drafts);
|
|
1399
1404
|
}, [
|
|
1400
1405
|
props.controller, batchDraft, changedObjectDraftKeys, configRouteOwner, dirty, draftOwner,
|
|
1401
|
-
configDrafts, configCandidate, arrayDrafts, objectDrafts, route.name, snapshot.router.currentFlowId, sourceDraft,
|
|
1406
|
+
configDrafts, configCandidate, arrayDrafts, objectDrafts, nestedPropertyRevision, objectVariantPreview, route.name, snapshot.router.currentFlowId, sourceDraft,
|
|
1402
1407
|
]);
|
|
1403
1408
|
useEffect(() => () => props.controller.setExternalDraftState(), [props.controller]);
|
|
1404
1409
|
const currentConfigPage = configPageMatches(configPage, configRoute) ? configPage : undefined;
|
|
@@ -1788,15 +1793,24 @@ export function ConsoleAppV4(props) {
|
|
|
1788
1793
|
const activeObjectDraft = activeObjectKey
|
|
1789
1794
|
? objectDrafts[activeObjectKey] ?? objectValueFromCandidate ?? objectValueFromUpdate ?? objectValueFromField ?? {}
|
|
1790
1795
|
: undefined;
|
|
1796
|
+
const activeObjectProperties = activeField?.definition.type === 'object' && activeObjectDraft
|
|
1797
|
+
? resolvePluginConfigObjectProperties(activeField.definition, activeObjectDraft, activeField.key).properties
|
|
1798
|
+
: undefined;
|
|
1791
1799
|
const activePropertyDefinition = route.name === 'configObjectPropertyEditor'
|
|
1792
1800
|
&& activeField?.definition.type === 'object' && route.propertyKey !== undefined
|
|
1793
|
-
?
|
|
1801
|
+
? activeObjectProperties?.[route.propertyKey]
|
|
1794
1802
|
?? (activeField.definition.additionalProperties === false
|
|
1795
1803
|
? undefined
|
|
1796
1804
|
: activeField.definition.additionalProperties)
|
|
1797
1805
|
: undefined;
|
|
1806
|
+
const activeVariantPreview = objectVariantPreview?.routeKey === routeKey ? objectVariantPreview : undefined;
|
|
1807
|
+
const nestedPropertyEditor = route.name === 'configObjectPropertyEditor' && route.stage === 'custom'
|
|
1808
|
+
&& !activeVariantPreview && (activePropertyDefinition?.type === 'array' || activePropertyDefinition?.type === 'object');
|
|
1809
|
+
useEffect(() => { setObjectVariantPreview(undefined); }, [routeKey]);
|
|
1798
1810
|
const activePropertySensitive = activeField?.sensitive === true
|
|
1799
1811
|
|| activePropertyDefinition?.sensitive === true;
|
|
1812
|
+
const activeFieldIsConst = activeField && 'const' in activeField.definition && activeField.definition.const !== undefined;
|
|
1813
|
+
const activePropertyIsConst = activePropertyDefinition && 'const' in activePropertyDefinition && activePropertyDefinition.const !== undefined;
|
|
1800
1814
|
useEffect(() => {
|
|
1801
1815
|
if (route.name !== 'configFieldEditor' || !activeField)
|
|
1802
1816
|
return;
|
|
@@ -1896,7 +1910,7 @@ export function ConsoleAppV4(props) {
|
|
|
1896
1910
|
|| Boolean(route.name === 'configUnavailable' && plugin)
|
|
1897
1911
|
|| Boolean(route.name === 'result' && snapshot.result && 'operationKind' in snapshot.result
|
|
1898
1912
|
&& snapshot.result.operationKind === 'portableInstall'));
|
|
1899
|
-
const characterInput = isCharacterInputMode(route, searchFocus)
|
|
1913
|
+
const characterInput = !activeVariantPreview && !activeFieldIsConst && !activePropertyIsConst && isCharacterInputMode(route, searchFocus)
|
|
1900
1914
|
|| route.name === 'operationReportPreview' && reportSaveMode;
|
|
1901
1915
|
const canOpenHelp = !tooSmall && !characterInput && !preparationRunning;
|
|
1902
1916
|
useEffect(() => {
|
|
@@ -3079,7 +3093,8 @@ export function ConsoleAppV4(props) {
|
|
|
3079
3093
|
const itemDefinition = activeTopField?.definition.type === 'array' ? activeTopField.definition.items : undefined;
|
|
3080
3094
|
const property = issue.path.property;
|
|
3081
3095
|
const label = property && itemDefinition?.type === 'object'
|
|
3082
|
-
?
|
|
3096
|
+
? activeObjectProperties?.[property]?.title ?? itemDefinition.properties?.[property]?.title ?? property
|
|
3097
|
+
: property ? activeObjectProperties?.[property]?.title ?? property : activeField?.title ?? issue.path.field;
|
|
3083
3098
|
return `${index === undefined ? '' : `第 ${Number(index) + 1} 项/`}${label}:${issue.message}`;
|
|
3084
3099
|
};
|
|
3085
3100
|
const commitObjectDraft = () => {
|
|
@@ -3099,11 +3114,11 @@ export function ConsoleAppV4(props) {
|
|
|
3099
3114
|
const openObjectProperty = (propertyKey, dynamic) => {
|
|
3100
3115
|
if (!activeField || activeField.definition.type !== 'object')
|
|
3101
3116
|
return;
|
|
3102
|
-
const definition =
|
|
3117
|
+
const definition = activeObjectProperties?.[propertyKey]
|
|
3103
3118
|
?? (activeField.definition.additionalProperties === false
|
|
3104
3119
|
? undefined
|
|
3105
3120
|
: activeField.definition.additionalProperties);
|
|
3106
|
-
if (!definition)
|
|
3121
|
+
if (!definition || 'const' in definition && definition.const !== undefined)
|
|
3107
3122
|
return;
|
|
3108
3123
|
const exists = activeObjectDraft && Object.hasOwn(activeObjectDraft, propertyKey);
|
|
3109
3124
|
go({
|
|
@@ -3121,12 +3136,36 @@ export function ConsoleAppV4(props) {
|
|
|
3121
3136
|
if (!activeField || activeField.definition.type !== 'object' || !activeObjectDraft)
|
|
3122
3137
|
return false;
|
|
3123
3138
|
const candidate = { ...activeObjectDraft, [propertyKey]: value };
|
|
3139
|
+
if (value === undefined)
|
|
3140
|
+
delete candidate[propertyKey];
|
|
3124
3141
|
const issues = validatePluginConfigValue(activeField.definition, candidate, activeField.key)
|
|
3125
3142
|
.filter((issue) => issue.path.property === propertyKey);
|
|
3126
3143
|
if (issues.length > 0) {
|
|
3127
3144
|
setInputError(issues.slice(0, 2).map(objectIssueText).join(';'));
|
|
3128
3145
|
return false;
|
|
3129
3146
|
}
|
|
3147
|
+
const variants = activeField.definition.variants;
|
|
3148
|
+
if (variants?.discriminator === propertyKey && activeObjectDraft[propertyKey] !== value) {
|
|
3149
|
+
const resolved = resolvePluginConfigObjectProperties(activeField.definition, candidate, activeField.key);
|
|
3150
|
+
if (resolved.issues.length) {
|
|
3151
|
+
setInputError(resolved.issues.slice(0, 2).map(objectIssueText).join(';'));
|
|
3152
|
+
return false;
|
|
3153
|
+
}
|
|
3154
|
+
const removed = [];
|
|
3155
|
+
for (const property of Object.keys(candidate)) {
|
|
3156
|
+
const definition = resolved.properties[property];
|
|
3157
|
+
if (activeObjectProperties?.[property] && !definition
|
|
3158
|
+
|| definition && 'const' in definition && definition.const !== undefined
|
|
3159
|
+
&& Object.hasOwn(candidate, property) && candidate[property] !== definition.const) {
|
|
3160
|
+
removed.push({ property, value: candidate[property] });
|
|
3161
|
+
delete candidate[property];
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
setObjectVariantPreview({ routeKey, value: candidate, removed });
|
|
3165
|
+
setFocus(0);
|
|
3166
|
+
setBatchTargetOffset(0);
|
|
3167
|
+
return false;
|
|
3168
|
+
}
|
|
3130
3169
|
updateObjectDraft(candidate);
|
|
3131
3170
|
return true;
|
|
3132
3171
|
};
|
|
@@ -3265,20 +3304,19 @@ export function ConsoleAppV4(props) {
|
|
|
3265
3304
|
const updatedValue = draft.updates[key];
|
|
3266
3305
|
const afterObject = field?.definition.type === 'object'
|
|
3267
3306
|
&& typeof updatedValue === 'object' && !Array.isArray(updatedValue) ? updatedValue : undefined;
|
|
3268
|
-
const childSummary = (property, value) => {
|
|
3307
|
+
const childSummary = (property, value, object) => {
|
|
3269
3308
|
if (value === undefined)
|
|
3270
3309
|
return '未设置';
|
|
3271
3310
|
if (field.sensitive || field.definition.type !== 'object')
|
|
3272
3311
|
return '已设置';
|
|
3273
|
-
const definition = field.definition.properties
|
|
3312
|
+
const definition = resolvePluginConfigObjectProperties(field.definition, object).properties[property]
|
|
3274
3313
|
?? (field.definition.additionalProperties === false
|
|
3275
3314
|
? undefined
|
|
3276
3315
|
: field.definition.additionalProperties);
|
|
3277
3316
|
if (definition?.sensitive)
|
|
3278
3317
|
return '已设置';
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
return value === '' ? '(空字符串)' : safeConfigText(String(value));
|
|
3318
|
+
return definition ? presentConfigValue({ definition, value, full: true }).text
|
|
3319
|
+
: safeConfigText(JSON.stringify(value));
|
|
3282
3320
|
};
|
|
3283
3321
|
const updatedChildren = beforeObject && afterObject
|
|
3284
3322
|
? [...new Set([...Object.keys(beforeObject), ...Object.keys(afterObject)])]
|
|
@@ -3296,7 +3334,7 @@ export function ConsoleAppV4(props) {
|
|
|
3296
3334
|
}
|
|
3297
3335
|
return left.localeCompare(right, 'en');
|
|
3298
3336
|
})
|
|
3299
|
-
.filter((property) => beforeObject[property]
|
|
3337
|
+
.filter((property) => !configValuesEqual(beforeObject[property], afterObject[property]))
|
|
3300
3338
|
.map((property) => {
|
|
3301
3339
|
const definition = field.definition.type === 'object'
|
|
3302
3340
|
? field.definition.properties?.[property]
|
|
@@ -3306,8 +3344,8 @@ export function ConsoleAppV4(props) {
|
|
|
3306
3344
|
: undefined;
|
|
3307
3345
|
return {
|
|
3308
3346
|
property,
|
|
3309
|
-
before: childSummary(property, beforeObject[property]),
|
|
3310
|
-
after: childSummary(property, afterObject[property]),
|
|
3347
|
+
before: childSummary(property, beforeObject[property], beforeObject),
|
|
3348
|
+
after: childSummary(property, afterObject[property], afterObject),
|
|
3311
3349
|
...(field.sensitive || definition?.sensitive ? { private: true } : {}),
|
|
3312
3350
|
};
|
|
3313
3351
|
})
|
|
@@ -5965,6 +6003,14 @@ export function ConsoleAppV4(props) {
|
|
|
5965
6003
|
actions = canUnset ? [{ label: '删除此覆盖并恢复继承', run: () => removeDraft(activeField.key) }] : [];
|
|
5966
6004
|
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StatusCard, { status: "warning", title: "\u4EC5\u53EF\u5220\u9664\u65E7\u503C", description: description }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true })] });
|
|
5967
6005
|
}
|
|
6006
|
+
else if ('const' in activeField.definition && activeField.definition.const !== undefined) {
|
|
6007
|
+
title = activeField.title;
|
|
6008
|
+
description = '这个值由插件固定,不能编辑。';
|
|
6009
|
+
const constant = activeField.definition.const;
|
|
6010
|
+
actions = activeField.definition.required && activeField.value === undefined
|
|
6011
|
+
? [{ label: '写入此固定值', run: () => updateDraft(activeField.key, constant) }] : [];
|
|
6012
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StaticRow, { title: `固定值 · ${presentConfigValue({ definition: activeField.definition, value: constant }).text}`, compact: true }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true })] });
|
|
6013
|
+
}
|
|
5968
6014
|
else if (showChoices) {
|
|
5969
6015
|
title = `选择${activeField.title}`;
|
|
5970
6016
|
description = activeField.type !== 'boolean' && activeField.allowCustom
|
|
@@ -6044,12 +6090,16 @@ export function ConsoleAppV4(props) {
|
|
|
6044
6090
|
if (objectError)
|
|
6045
6091
|
description = objectError;
|
|
6046
6092
|
help = '↑↓ 移动 · Enter 编辑 · Esc 取消';
|
|
6047
|
-
const fixedEntries = Object.entries(
|
|
6093
|
+
const fixedEntries = Object.entries(activeObjectProperties ?? {});
|
|
6048
6094
|
const fixedKeys = new Set(fixedEntries.map(([property]) => property));
|
|
6049
6095
|
const dynamicKeys = Object.keys(activeObjectDraft)
|
|
6050
6096
|
.filter((property) => !fixedKeys.has(property))
|
|
6051
6097
|
.sort((left, right) => left.localeCompare(right, 'en'));
|
|
6052
6098
|
const propertySummary = (property, definition) => {
|
|
6099
|
+
if ('const' in definition && definition.const !== undefined) {
|
|
6100
|
+
const text = presentConfigValue({ definition, value: definition.const }).text;
|
|
6101
|
+
return `${'required' in definition && definition.required && !Object.hasOwn(activeObjectDraft, property) ? '必填 · ' : ''}固定值 · ${text}`;
|
|
6102
|
+
}
|
|
6053
6103
|
const presentation = presentConfigValue({ definition,
|
|
6054
6104
|
value: activeObjectDraft[property], privateValue: activeField.sensitive,
|
|
6055
6105
|
configured: Object.hasOwn(activeObjectDraft, property),
|
|
@@ -6062,12 +6112,30 @@ export function ConsoleAppV4(props) {
|
|
|
6062
6112
|
label: definition.title ?? property,
|
|
6063
6113
|
description: definition.description,
|
|
6064
6114
|
meta: propertySummary(property, definition),
|
|
6065
|
-
|
|
6115
|
+
disabled: 'const' in definition && definition.const !== undefined
|
|
6116
|
+
&& !(definition.required && !Object.hasOwn(activeObjectDraft, property)) ? '插件固定值,不能编辑' : undefined,
|
|
6117
|
+
run: () => {
|
|
6118
|
+
if ('const' in definition && definition.const !== undefined) {
|
|
6119
|
+
updateObjectDraft({ ...activeObjectDraft, [property]: definition.const });
|
|
6120
|
+
}
|
|
6121
|
+
else
|
|
6122
|
+
openObjectProperty(property, false);
|
|
6123
|
+
},
|
|
6066
6124
|
})),
|
|
6067
6125
|
...dynamicKeys.map((property) => ({
|
|
6068
6126
|
label: property,
|
|
6069
|
-
meta:
|
|
6070
|
-
|
|
6127
|
+
meta: objectDefinition.additionalProperties === false
|
|
6128
|
+
? `不适用 · ${safeConfigText(JSON.stringify(activeObjectDraft[property]))}`
|
|
6129
|
+
: propertySummary(property, objectDefinition.additionalProperties),
|
|
6130
|
+
run: () => {
|
|
6131
|
+
if (objectDefinition.additionalProperties !== false)
|
|
6132
|
+
openObjectProperty(property, true);
|
|
6133
|
+
else {
|
|
6134
|
+
const next = { ...activeObjectDraft };
|
|
6135
|
+
delete next[property];
|
|
6136
|
+
updateObjectDraft(next);
|
|
6137
|
+
}
|
|
6138
|
+
},
|
|
6071
6139
|
})),
|
|
6072
6140
|
];
|
|
6073
6141
|
const objectOperationActions = [
|
|
@@ -6131,7 +6199,31 @@ export function ConsoleAppV4(props) {
|
|
|
6131
6199
|
const definition = activePropertyDefinition;
|
|
6132
6200
|
const propertyTitle = definition && property ? definition.title ?? property : '动态键';
|
|
6133
6201
|
breadcrumb = `${plugin.displayName} / 设置 / ${activeField.title} / ${propertyTitle}`;
|
|
6134
|
-
if (
|
|
6202
|
+
if (activeVariantPreview) {
|
|
6203
|
+
title = '确认分支切换';
|
|
6204
|
+
description = '确认后仅更新当前对象草稿;完整设置仍需 Review 后保存。';
|
|
6205
|
+
const candidateIssues = validatePluginConfigValue(activeField.definition, activeVariantPreview.value, activeField.key);
|
|
6206
|
+
readingText = [
|
|
6207
|
+
activeVariantPreview.removed.length ? '将移除这些旧值:' : '没有需要移除的旧值。',
|
|
6208
|
+
...activeVariantPreview.removed.map((entry) => `${entry.property} = ${safeConfigText(JSON.stringify(entry.value))}`),
|
|
6209
|
+
'切换后的实际配置:', safeConfigText(JSON.stringify(activeVariantPreview.value, null, 2)),
|
|
6210
|
+
...(candidateIssues.length ? ['需要补充或修正:', ...candidateIssues.map(objectIssueText)] : []),
|
|
6211
|
+
].join('\n');
|
|
6212
|
+
actions = [{ label: '使用此候选草稿', run: () => {
|
|
6213
|
+
updateObjectDraft(activeVariantPreview.value);
|
|
6214
|
+
if (candidateIssues.length)
|
|
6215
|
+
setObjectError(candidateIssues.slice(0, 2).map(objectIssueText).join(';'));
|
|
6216
|
+
setObjectVariantPreview(undefined);
|
|
6217
|
+
back();
|
|
6218
|
+
} }, { label: '取消切换', run: () => { setObjectVariantPreview(undefined); back(); } }];
|
|
6219
|
+
content = _jsxs(Box, { flexDirection: "column", children: [readingPage(readingText, size.columns - 2, Math.max(1, pageActionBudget(4))), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true })] });
|
|
6220
|
+
}
|
|
6221
|
+
else if (property !== undefined && definition && 'const' in definition && definition.const !== undefined) {
|
|
6222
|
+
title = propertyTitle;
|
|
6223
|
+
description = '这个值由插件固定,不能编辑。';
|
|
6224
|
+
content = _jsx(StaticRow, { title: `固定值 · ${presentConfigValue({ definition, value: definition.const }).text}`, compact: true });
|
|
6225
|
+
}
|
|
6226
|
+
else if (route.stage === 'key') {
|
|
6135
6227
|
title = '输入新键名';
|
|
6136
6228
|
description = inputError ?? '键名和属性数量会按插件规则检查。';
|
|
6137
6229
|
help = '输入 · Enter 继续 · Ctrl-U 清空输入 · Esc 取消';
|
|
@@ -6156,6 +6248,11 @@ export function ConsoleAppV4(props) {
|
|
|
6156
6248
|
label: route.dynamic ? '删除动态键' : '删除属性',
|
|
6157
6249
|
status: 'error',
|
|
6158
6250
|
run: () => {
|
|
6251
|
+
if (activeField.definition.type === 'object' && activeField.definition.variants?.discriminator === property) {
|
|
6252
|
+
if (updateObjectProperty(property, undefined))
|
|
6253
|
+
back();
|
|
6254
|
+
return;
|
|
6255
|
+
}
|
|
6159
6256
|
const next = { ...activeObjectDraft };
|
|
6160
6257
|
delete next[property];
|
|
6161
6258
|
updateObjectDraft(next);
|
|
@@ -6203,7 +6300,7 @@ export function ConsoleAppV4(props) {
|
|
|
6203
6300
|
...(definition.choices?.presets ?? []).map((preset) => ({
|
|
6204
6301
|
label: `${preset.title}${preset.recommended ? '(推荐)' : ''}`,
|
|
6205
6302
|
description: preset.description,
|
|
6206
|
-
selected: !activePropertySensitive && current
|
|
6303
|
+
selected: !activePropertySensitive && configValuesEqual(current, preset.value),
|
|
6207
6304
|
run: () => { if (updateObjectProperty(property, preset.value))
|
|
6208
6305
|
back(); },
|
|
6209
6306
|
})),
|
|
@@ -6217,6 +6314,13 @@ export function ConsoleAppV4(props) {
|
|
|
6217
6314
|
];
|
|
6218
6315
|
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6219
6316
|
}
|
|
6317
|
+
else if (property !== undefined && definition && (definition.type === 'array' || definition.type === 'object')) {
|
|
6318
|
+
title = `编辑${propertyTitle}`;
|
|
6319
|
+
description = '确认后更新当前对象草稿;Esc 取消此属性的全部修改。';
|
|
6320
|
+
help = '↑↓ 移动 · Enter 编辑 · a 操作 · c 使用 · Esc 取消';
|
|
6321
|
+
content = _jsx(ConfigLeafEditor, { definition: definition, value: activeObjectDraft[property], propertyKey: property, columns: size.columns, rowBudget: pageActionBudget(1), active: !overlay && !tooSmall && !busy, error: inputError, onDraftChange: setNestedPropertyRevision, onCancel: back, onConfirm: (value) => { if (!updateObjectProperty(property, value))
|
|
6322
|
+
return false; back(); return true; } }, `${snapshot.router.currentFrameId}:${property}`);
|
|
6323
|
+
}
|
|
6220
6324
|
else if (property !== undefined && definition) {
|
|
6221
6325
|
title = activePropertySensitive ? '输入敏感值' : `输入${propertyTitle}`;
|
|
6222
6326
|
description = inputError ?? (activePropertySensitive ? '输入已隐藏。' : definition.description ?? '按 Enter 使用输入值。');
|
|
@@ -9270,6 +9374,11 @@ export function ConsoleAppV4(props) {
|
|
|
9270
9374
|
}
|
|
9271
9375
|
return;
|
|
9272
9376
|
}
|
|
9377
|
+
if (nestedPropertyEditor && !overlay) {
|
|
9378
|
+
if (key.ctrl && input.toLowerCase() === 'c')
|
|
9379
|
+
requestConfirmedExit();
|
|
9380
|
+
return;
|
|
9381
|
+
}
|
|
9273
9382
|
if (arrayToolsOpen && activeArrayDraft) {
|
|
9274
9383
|
if (key.escape)
|
|
9275
9384
|
setArrayToolsOpen(false);
|
|
@@ -9866,6 +9975,7 @@ export function ConsoleAppV4(props) {
|
|
|
9866
9975
|
return;
|
|
9867
9976
|
}
|
|
9868
9977
|
if (route.name === 'configFieldEditor'
|
|
9978
|
+
&& !activeFieldIsConst
|
|
9869
9979
|
&& (route.editor === 'string' || route.editor === 'number')
|
|
9870
9980
|
&& ((activeField?.choices?.length ?? 0) === 0 || route.mode === 'custom')
|
|
9871
9981
|
&& ['project', 'user'].some((scope) => configLayerPages[scope]?.groups.flatMap((group) => group.fields)
|
|
@@ -9912,6 +10022,8 @@ export function ConsoleAppV4(props) {
|
|
|
9912
10022
|
}
|
|
9913
10023
|
if (route.name === 'configObjectPropertyEditor'
|
|
9914
10024
|
&& (route.stage === 'key' || route.stage === 'custom')
|
|
10025
|
+
&& !activeVariantPreview
|
|
10026
|
+
&& !activePropertyIsConst
|
|
9915
10027
|
&& activeField?.definition.type === 'object'
|
|
9916
10028
|
&& activeObjectDraft) {
|
|
9917
10029
|
if (key.escape) {
|