diff --git a/apps/cli/config/agent-presets/cordis/preset.yml b/apps/cli/config/agent-presets/cordis/preset.yml
index b4d2e6a6f7..f54750872a 100644
--- a/apps/cli/config/agent-presets/cordis/preset.yml
+++ b/apps/cli/config/agent-presets/cordis/preset.yml
@@ -1,2 +1,3 @@
name: 创造模式
description: 标准模式加上自指工具集,可以读改自己运行的这套组装,并据此创作新的预设。
+order: 3
diff --git a/apps/cli/config/agent-presets/minimal/preset.yml b/apps/cli/config/agent-presets/minimal/preset.yml
index 957796b6a0..4c9c3b3d7f 100644
--- a/apps/cli/config/agent-presets/minimal/preset.yml
+++ b/apps/cli/config/agent-presets/minimal/preset.yml
@@ -1,2 +1,3 @@
name: 极简模式
description: 只向模型呈现 bash 与 str_replace_editor,适合 benchmark 与最小复现。
+order: 2
diff --git a/apps/cli/config/agent-presets/standard/preset.yml b/apps/cli/config/agent-presets/standard/preset.yml
index 090576f0f2..8eddfbde48 100644
--- a/apps/cli/config/agent-presets/standard/preset.yml
+++ b/apps/cli/config/agent-presets/standard/preset.yml
@@ -1,2 +1,3 @@
name: 标准模式
description: 完整的编码 agent:文件读写、shell、检索、计划、委派与工作流。
+order: 1
diff --git a/docs/config-catalog.md b/docs/config-catalog.md
index 3761927cd7..822fecf79b 100644
--- a/docs/config-catalog.md
+++ b/docs/config-catalog.md
@@ -139,7 +139,7 @@ export interface PresetRoot {
export type PresetTrust = 'system' | 'user'
```
-Source: [`packages/preset/agent-presets/src/types.ts:33`](../packages/preset/agent-presets/src/types.ts)
+Source: [`packages/preset/agent-presets/src/types.ts:35`](../packages/preset/agent-presets/src/types.ts)
## `@deepseek-ai/dsh-agent-spine-demo`
diff --git a/packages/client/ui-agent-preset/src/client/AgentPresetSection.module.css b/packages/client/ui-agent-preset/src/client/AgentPresetSection.module.css
index ae296a7022..cfde11ee90 100644
--- a/packages/client/ui-agent-preset/src/client/AgentPresetSection.module.css
+++ b/packages/client/ui-agent-preset/src/client/AgentPresetSection.module.css
@@ -52,6 +52,9 @@
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
+ /* Every row the same height, so a short description does not make its card
+ shorter than the one beside it. */
+ grid-auto-rows: 1fr;
gap: 12px;
}
@@ -64,6 +67,7 @@
transition: border-color .16s, background .16s;
}
+
.card:hover:not(.cardActive) {
border-color: var(--dsw-alias-label-dimmed);
}
@@ -76,6 +80,7 @@
/* The card body is the control that picks the preset. */
.cardMain {
+ flex: 1;
appearance: none;
border: 0;
background: none;
@@ -111,11 +116,25 @@
line-height: 1.4;
}
+.badge,
+.inUse {
+ border-radius: 999px;
+ padding: 1px 8px;
+ font-size: 11px;
+ line-height: 17px;
+ white-space: nowrap;
+ font-weight: 500;
+}
+
+.badge {
+ border: 1px solid var(--dsw-alias-border-l2);
+ color: var(--dsw-alias-label-tertiary);
+}
+
.inUse {
margin-left: auto;
- font-size: 11px;
- color: var(--dsw-alias-label-tertiary);
- white-space: nowrap;
+ background: var(--dsw-alias-label-primary);
+ color: var(--dsw-alias-bg-layer-3);
}
.cardDesc {
@@ -123,6 +142,7 @@
line-height: 1.55;
color: var(--dsw-alias-label-secondary);
flex: 1;
+ min-height: 42px;
}
.cardId {
@@ -133,6 +153,7 @@
.cardFoot {
display: flex;
+ justify-content: flex-end;
gap: 2px;
padding: 6px 10px;
border-top: 1px solid var(--dsw-alias-border-l2);
@@ -141,6 +162,7 @@
/* Icon-only actions: the label rides `title` so the row stays quiet until
someone reaches for it. */
.iconButton {
+ position: relative;
appearance: none;
border: 0;
border-radius: 7px;
@@ -162,6 +184,29 @@
outline-offset: -1px;
}
+.iconButton::after {
+ content: attr(data-tip);
+ position: absolute;
+ bottom: calc(100% + 6px);
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 3px 8px;
+ border-radius: 6px;
+ background: var(--dsw-alias-label-primary);
+ color: var(--dsw-alias-bg-layer-3);
+ font-size: 11px;
+ line-height: 17px;
+ white-space: nowrap;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity .12s;
+}
+
+.iconButton:hover::after,
+.iconButton:focus-visible::after {
+ opacity: 1;
+}
+
.iconDanger:hover:not(:disabled) {
background: var(--dsw-alias-interactive-bg-hover-danger);
color: var(--dsw-alias-state-error-primary);
@@ -255,11 +300,38 @@
gap: 8px;
}
-.addCard {
- border: 1px solid var(--dsw-alias-border-l2);
- border-radius: 12px;
- background: var(--dsw-alias-bg-layer-3);
- padding: 14px 16px;
+.editorBar {
+ display: flex;
+ align-items: baseline;
+ gap: 12px;
+ padding-bottom: 4px;
+ border-bottom: 1px solid var(--dsw-alias-border-l2);
+}
+
+.backButton {
+ appearance: none;
+ border: 0;
+ background: none;
+ padding: 0;
+ font: inherit;
+ font-size: 13px;
+ color: var(--dsw-alias-label-tertiary);
+ cursor: pointer;
+}
+
+.backButton:hover {
+ color: var(--dsw-alias-label-primary);
+}
+
+.backButton:focus-visible {
+ outline: 2px solid var(--dsw-alias-brand-primary);
+ outline-offset: 2px;
+ border-radius: 4px;
+}
+
+.editorTitle {
+ font-size: 14px;
+ font-weight: 600;
}
.addButton {
diff --git a/packages/client/ui-agent-preset/src/client/AgentPresetSection.tsx b/packages/client/ui-agent-preset/src/client/AgentPresetSection.tsx
index 18fc0a646d..f8ee745a54 100644
--- a/packages/client/ui-agent-preset/src/client/AgentPresetSection.tsx
+++ b/packages/client/ui-agent-preset/src/client/AgentPresetSection.tsx
@@ -174,13 +174,32 @@ export function AgentPresetSection(props: AgentPresetSectionProps): ReactNode {
const { draft } = state
const blocker = draft === null ? undefined : draftBlocker(draft, state.rows)
- const editorActions = {
- close: props.close,
- save: props.save,
- setContent: props.setContent,
- setDescription: props.setDescription,
- setId: props.setId,
- setName: props.setName,
+ // Editing replaces the list rather than hanging off the end of it: the form
+ // is tall, and a column of the card grid is far too narrow to hold it.
+ if (draft !== null) {
+ const editorActions = {
+ close: props.close,
+ save: props.save,
+ setContent: props.setContent,
+ setDescription: props.setDescription,
+ setId: props.setId,
+ setName: props.setName,
+ }
+ return (
+
+
+
+
+ {draft.creating
+ ? `${t('newPreset')} · ${t('copyOf')} ${draft.source}`
+ : `${draft.writable ? t('edit') : t('view')} · ${draft.name === '' ? draft.source : draft.name}`}
+
+
+
+
+ )
}
return (
@@ -226,7 +245,7 @@ export function AgentPresetSection(props: AgentPresetSectionProps): ReactNode {