You've already forked agentic-coding-workflow
feat(web): AgentKindForm component (Naive UI form with env editor)
This commit is contained in:
@@ -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>
|
||||||
Reference in New Issue
Block a user