feat(web): AgentKindForm component (Naive UI form with env editor)

This commit is contained in:
2026-05-07 12:00:16 +08:00
parent b044c86728
commit 6e8a9ee8d6
+177
View File
@@ -0,0 +1,177 @@
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
import { NInput, NButton, NCheckbox } from 'naive-ui'
const props = defineProps<{
modelValue: {
name: string
display_name: string
description: string
binary_path: string
args: string[]
env: Record<string, string>
enabled: boolean
}
isEdit: boolean
existingEnvKeys?: string[]
}>()
const emit = defineEmits<{
(e: 'update:modelValue', value: typeof props.modelValue): void
(e: 'submit'): void
(e: 'cancel'): void
}>()
const local = ref({ ...props.modelValue })
watch(
() => props.modelValue,
(v) => {
local.value = { ...v }
},
)
watch(local, (v) => emit('update:modelValue', v), { deep: true })
const argsText = computed({
get: () => local.value.args.join('\n'),
set: (v: string) => {
local.value.args = v.split('\n').filter((x) => x.trim() !== '')
},
})
interface EnvRow {
k: string
v: string
}
const envEntries = ref<EnvRow[]>(
Object.entries(local.value.env).map(([k, v]) => ({ k, v })),
)
watch(
envEntries,
(entries) => {
const m: Record<string, string> = {}
for (const { k, v } of entries) {
if (k.trim()) m[k] = v
}
local.value.env = m
},
{ deep: true },
)
function addEnv() {
envEntries.value.push({ k: '', v: '' })
}
function removeEnv(idx: number) {
envEntries.value.splice(idx, 1)
}
</script>
<template>
<form
class="space-y-4"
@submit.prevent="emit('submit')"
>
<div>
<label class="block text-sm font-medium mb-1">Name</label>
<NInput
v-model:value="local.name"
:readonly="isEdit"
placeholder="claude_code"
/>
<p
v-if="isEdit"
class="text-xs text-gray-500 mt-1"
>
Name cannot be changed after creation
</p>
</div>
<div>
<label class="block text-sm font-medium mb-1">Display Name</label>
<NInput
v-model:value="local.display_name"
placeholder="Claude Code"
/>
</div>
<div>
<label class="block text-sm font-medium mb-1">Description</label>
<NInput
v-model:value="local.description"
type="textarea"
:autosize="{ minRows: 2, maxRows: 6 }"
/>
</div>
<div>
<label class="block text-sm font-medium mb-1">Binary Path</label>
<NInput
v-model:value="local.binary_path"
placeholder="claude-code or /usr/local/bin/claude-code"
/>
</div>
<div>
<label class="block text-sm font-medium mb-1">Args (one per line)</label>
<NInput
v-model:value="argsText"
type="textarea"
:autosize="{ minRows: 3, maxRows: 8 }"
placeholder="--acp"
/>
</div>
<div>
<label class="block text-sm font-medium mb-1">Env</label>
<p
v-if="isEdit && existingEnvKeys?.length"
class="text-xs text-gray-500 mb-2"
>
Existing keys (values hidden): {{ existingEnvKeys.join(', ') }}.
Edit below to replace entirely.
</p>
<div
v-for="(e, idx) in envEntries"
:key="idx"
class="flex gap-2 mb-2"
>
<NInput
v-model:value="e.k"
placeholder="KEY"
class="flex-1"
/>
<NInput
v-model:value="e.v"
type="password"
show-password-on="click"
placeholder="value"
class="flex-1"
/>
<NButton
quaternary
@click="removeEnv(idx)"
>
×
</NButton>
</div>
<NButton
size="small"
dashed
@click="addEnv"
>
+ Add
</NButton>
</div>
<div class="flex items-center gap-2">
<NCheckbox v-model:checked="local.enabled">
Enabled
</NCheckbox>
</div>
<div class="flex gap-2">
<NButton
type="primary"
attr-type="submit"
>
Save
</NButton>
<NButton @click="emit('cancel')">
Cancel
</NButton>
</div>
</form>
</template>