Files
pikasTech-HWLAB/web/hwlab-cloud-web/src/components/workbench/CommandComposer.vue
T

83 lines
4.5 KiB
Vue

<script setup lang="ts">
import { computed, ref } from "vue";
import { useWorkbenchStore } from "@/stores/workbench";
const workbench = useWorkbenchStore();
const draft = ref("");
const draftsOpen = ref(false);
const draftText = computed(() => draft.value.trim());
const primaryAction = computed<"turn" | "steer" | "cancel">(() => {
if (workbench.composer.submitMode === "steer") return draftText.value ? "steer" : "cancel";
return "turn";
});
const primaryLabel = computed(() => primaryAction.value === "cancel" ? "取消" : primaryAction.value === "steer" ? "Steer" : "发送");
const primaryModeLabel = computed(() => {
if (workbench.composer.disabledReason) return workbench.composer.disabledReason;
if (primaryAction.value === "cancel") return `运行中 ${workbench.composer.targetTraceId ?? "trace"}`;
if (primaryAction.value === "steer") return `steer ${workbench.composer.targetTraceId}`;
return "turn / 新请求";
});
const primaryDisabled = computed(() => {
if (primaryAction.value === "cancel") return workbench.composer.disabled || !workbench.composer.targetTraceId;
return workbench.composer.disabled || !draftText.value;
});
async function submit(): Promise<void> {
const value = draft.value;
if (primaryAction.value === "cancel") {
if (primaryDisabled.value) return;
await workbench.cancelRunningTrace();
return;
}
if (!value.trim() || workbench.composer.disabled) return;
draft.value = "";
const accepted = await workbench.submitMessage(value);
if (!accepted && !draft.value.trim()) draft.value = value;
}
async function submitFromInput(): Promise<void> {
if (!draftText.value) return;
await submit();
}
function pickDraft(text: string): void {
draft.value = text;
draftsOpen.value = false;
workbench.recordActivity("draft-pick");
}
</script>
<template>
<form id="command-form" class="command-composer" :title="workbench.composer.disabledReason || (primaryAction === 'cancel' ? `取消运行中的 turn: ${workbench.composer.targetTraceId}` : primaryAction === 'steer' ? `Steer 运行中的 turn: ${workbench.composer.targetTraceId}` : '发送新 turn')" @submit.prevent="submit">
<div class="composer-toolbar">
<label class="composer-field" for="code-agent-provider-profile">
<span>模型通道</span>
<select id="code-agent-provider-profile" v-model="workbench.providerProfile" @change="workbench.setProviderProfile(($event.target as HTMLSelectElement).value)">
<option v-for="option in workbench.providerOptions" :key="option.value" :value="option.value">
{{ option.label }}{{ option.configured === false ? ' · 未配置' : '' }}
</option>
</select>
</label>
<button id="command-drafts-toggle" class="btn btn-secondary btn-sm" type="button" :aria-expanded="draftsOpen" aria-controls="command-drafts-panel" @click="draftsOpen = !draftsOpen">最近输入</button>
<button id="command-clear" class="btn btn-secondary btn-sm" type="button" @click="draft = ''; workbench.clearSessionMessages()">清空</button>
</div>
<section v-if="draftsOpen && workbench.recentDrafts.length > 0" id="command-drafts-panel" class="drafts-list" data-drafts-list aria-label="最近发送过的草稿">
<header class="drafts-list-head">
<p class="page-eyebrow">最近输入</p>
<button class="btn btn-secondary btn-sm" type="button" @click="workbench.clearRecentDrafts">清空记录</button>
</header>
<div class="drafts-list-items" role="list">
<button v-for="item in workbench.recentDrafts" :key="`${item.ts}-${item.text}`" class="draft-chip" type="button" role="listitem" :title="`${item.ts.slice(0, 19)} · ${item.text}`" @click="pickDraft(workbench.pickDraft(item))">
{{ item.text.length > 40 ? `${item.text.slice(0, 40)}...` : item.text }}
</button>
</div>
</section>
<div class="composer-actions">
<span v-if="workbench.composer.disabledReason" class="composer-warning">{{ workbench.composer.disabledReason }}</span>
<span v-else class="composer-mode" :data-mode="primaryAction">{{ primaryModeLabel }}</span>
<button id="command-send" class="btn btn-primary" type="submit" :data-action="primaryAction" :disabled="primaryDisabled">{{ primaryLabel }}</button>
</div>
<textarea id="command-input" v-model="draft" rows="3" placeholder="输入任务,Enter 发送,Shift+Enter 换行" :disabled="false" @input="workbench.recordActivity('typing')" @keydown.enter.exact.prevent="submitFromInput" />
</form>
</template>