Align MCP OAuth and tool approval cards with agent tool timeline UX.
Build and Push Docker Image / build-ui (push) Has been cancelled
Build and Push Docker Image / merge (push) Has been cancelled
Build and Push Docker Image / build-docreader (push) Has been cancelled
Build and Push Docker Image / build-sandbox (push) Has been cancelled
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Image / build-ui (push) Has been cancelled
Build and Push Docker Image / merge (push) Has been cancelled
Build and Push Docker Image / build-docreader (push) Has been cancelled
Build and Push Docker Image / build-sandbox (push) Has been cancelled
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Unify inline interaction styling with tool steps: timeline icon placement, shimmer pending state, collapsible JSON args, and lighter status rows.
This commit is contained in:
@@ -5036,6 +5036,7 @@ export default {
|
|||||||
toolApproval: {
|
toolApproval: {
|
||||||
banner: 'This MCP tool requires human approval. Review parameters before execution.',
|
banner: 'This MCP tool requires human approval. Review parameters before execution.',
|
||||||
waiting: 'Awaiting review · {target}',
|
waiting: 'Awaiting review · {target}',
|
||||||
|
waitingStatus: 'Awaiting review',
|
||||||
targetWithTool: '{service} › {tool}',
|
targetWithTool: '{service} › {tool}',
|
||||||
titleWithTarget: 'Review · {service} › {tool}',
|
titleWithTarget: 'Review · {service} › {tool}',
|
||||||
resolvedApproved: 'Approved · {target}',
|
resolvedApproved: 'Approved · {target}',
|
||||||
@@ -5058,6 +5059,7 @@ export default {
|
|||||||
mcpOAuth: {
|
mcpOAuth: {
|
||||||
banner: 'This MCP service requires OAuth authorization before it can be used',
|
banner: 'This MCP service requires OAuth authorization before it can be used',
|
||||||
waiting: 'Awaiting authorization · {target}',
|
waiting: 'Awaiting authorization · {target}',
|
||||||
|
waitingStatus: 'Awaiting authorization',
|
||||||
targetWithTool: '{service} › {tool}',
|
targetWithTool: '{service} › {tool}',
|
||||||
titleWithService: 'OAuth · {service}',
|
titleWithService: 'OAuth · {service}',
|
||||||
titleWithTool: 'OAuth · {service} › {tool}',
|
titleWithTool: 'OAuth · {service} › {tool}',
|
||||||
|
|||||||
@@ -5053,6 +5053,7 @@ export default {
|
|||||||
toolApproval: {
|
toolApproval: {
|
||||||
banner: '이 MCP 도구는 수동 승인이 필요합니다. 실행 전 매개변수를 확인하세요.',
|
banner: '이 MCP 도구는 수동 승인이 필요합니다. 실행 전 매개변수를 확인하세요.',
|
||||||
waiting: '승인 대기 · {target}',
|
waiting: '승인 대기 · {target}',
|
||||||
|
waitingStatus: '승인 대기',
|
||||||
targetWithTool: '{service} › {tool}',
|
targetWithTool: '{service} › {tool}',
|
||||||
titleWithTarget: '검토 · {service} › {tool}',
|
titleWithTarget: '검토 · {service} › {tool}',
|
||||||
resolvedApproved: '승인됨 · {target}',
|
resolvedApproved: '승인됨 · {target}',
|
||||||
@@ -5075,6 +5076,7 @@ export default {
|
|||||||
mcpOAuth: {
|
mcpOAuth: {
|
||||||
banner: '이 MCP 서비스는 OAuth 인증 후에 사용할 수 있습니다',
|
banner: '이 MCP 서비스는 OAuth 인증 후에 사용할 수 있습니다',
|
||||||
waiting: '인증 대기 · {target}',
|
waiting: '인증 대기 · {target}',
|
||||||
|
waitingStatus: '인증 대기',
|
||||||
targetWithTool: '{service} › {tool}',
|
targetWithTool: '{service} › {tool}',
|
||||||
titleWithService: 'OAuth · {service}',
|
titleWithService: 'OAuth · {service}',
|
||||||
titleWithTool: 'OAuth · {service} › {tool}',
|
titleWithTool: 'OAuth · {service} › {tool}',
|
||||||
|
|||||||
@@ -4553,6 +4553,7 @@ export default {
|
|||||||
toolApproval: {
|
toolApproval: {
|
||||||
banner: 'Этот инструмент MCP требует подтверждения. Проверьте параметры.',
|
banner: 'Этот инструмент MCP требует подтверждения. Проверьте параметры.',
|
||||||
waiting: 'Ожидание проверки · {target}',
|
waiting: 'Ожидание проверки · {target}',
|
||||||
|
waitingStatus: 'Ожидание проверки',
|
||||||
targetWithTool: '{service} › {tool}',
|
targetWithTool: '{service} › {tool}',
|
||||||
titleWithTarget: 'Проверка · {service} › {tool}',
|
titleWithTarget: 'Проверка · {service} › {tool}',
|
||||||
resolvedApproved: 'Подтверждено · {target}',
|
resolvedApproved: 'Подтверждено · {target}',
|
||||||
@@ -4575,6 +4576,7 @@ export default {
|
|||||||
mcpOAuth: {
|
mcpOAuth: {
|
||||||
banner: 'Этот MCP-сервис требует авторизации OAuth перед использованием',
|
banner: 'Этот MCP-сервис требует авторизации OAuth перед использованием',
|
||||||
waiting: 'Ожидание авторизации · {target}',
|
waiting: 'Ожидание авторизации · {target}',
|
||||||
|
waitingStatus: 'Ожидание авторизации',
|
||||||
targetWithTool: '{service} › {tool}',
|
targetWithTool: '{service} › {tool}',
|
||||||
titleWithService: 'OAuth · {service}',
|
titleWithService: 'OAuth · {service}',
|
||||||
titleWithTool: 'OAuth · {service} › {tool}',
|
titleWithTool: 'OAuth · {service} › {tool}',
|
||||||
|
|||||||
@@ -5049,6 +5049,7 @@ export default {
|
|||||||
toolApproval: {
|
toolApproval: {
|
||||||
banner: "该 MCP 工具已标记为「需人工审核」,确认参数后再执行",
|
banner: "该 MCP 工具已标记为「需人工审核」,确认参数后再执行",
|
||||||
waiting: "等待审核 · {target}",
|
waiting: "等待审核 · {target}",
|
||||||
|
waitingStatus: "等待审核",
|
||||||
targetWithTool: "{service} › {tool}",
|
targetWithTool: "{service} › {tool}",
|
||||||
titleWithTarget: "人工审核 · {service} › {tool}",
|
titleWithTarget: "人工审核 · {service} › {tool}",
|
||||||
resolvedApproved: "已通过 · {target}",
|
resolvedApproved: "已通过 · {target}",
|
||||||
@@ -5071,6 +5072,7 @@ export default {
|
|||||||
mcpOAuth: {
|
mcpOAuth: {
|
||||||
banner: "该 MCP 服务需要 OAuth 授权后才能调用",
|
banner: "该 MCP 服务需要 OAuth 授权后才能调用",
|
||||||
waiting: "等待授权 · {target}",
|
waiting: "等待授权 · {target}",
|
||||||
|
waitingStatus: "等待授权",
|
||||||
targetWithTool: "{service} › {tool}",
|
targetWithTool: "{service} › {tool}",
|
||||||
titleWithService: "OAuth 授权 · {service}",
|
titleWithService: "OAuth 授权 · {service}",
|
||||||
titleWithTool: "OAuth 授权 · {service} › {tool}",
|
titleWithTool: "OAuth 授权 · {service} › {tool}",
|
||||||
|
|||||||
@@ -1,35 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="action-card interaction-inline" :class="cardClass">
|
<div class="action-card interaction-inline" :class="{ 'action-pending': !resolved }">
|
||||||
<div class="action-header no-results">
|
<div class="action-header no-results">
|
||||||
<div class="action-title">
|
<div class="action-title">
|
||||||
<t-icon class="action-title-icon" :name="headerIcon" />
|
<t-icon class="action-title-icon" :name="headerIcon" />
|
||||||
<span class="action-name">{{ titleLine }}</span>
|
<span class="action-name">{{ mainTitle }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="interaction-status-summary">
|
||||||
|
<div class="results-summary-text">
|
||||||
|
<span v-if="resolved" class="status-label">{{ statusLine }}</span>
|
||||||
<span v-if="!resolved" class="inline-actions">
|
<span v-if="!resolved" class="inline-actions">
|
||||||
<button
|
<button type="button" class="inline-action" :disabled="canceling || authorizing" @click="skip">
|
||||||
type="button"
|
|
||||||
class="inline-action"
|
|
||||||
:disabled="canceling || authorizing"
|
|
||||||
@click="skip"
|
|
||||||
>
|
|
||||||
{{ $t('agentStream.mcpOAuth.skip') }}
|
{{ $t('agentStream.mcpOAuth.skip') }}
|
||||||
</button>
|
</button>
|
||||||
<span class="inline-dot">·</span>
|
<span class="inline-dot">·</span>
|
||||||
<button
|
<button type="button" class="inline-action is-primary" :disabled="authorizing || canceling"
|
||||||
type="button"
|
@click="authorize">
|
||||||
class="inline-action is-primary"
|
|
||||||
:disabled="authorizing || canceling"
|
|
||||||
@click="authorize"
|
|
||||||
>
|
|
||||||
{{ $t('agentStream.mcpOAuth.authorize') }}
|
{{ $t('agentStream.mcpOAuth.authorize') }}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<template v-if="!resolved && secondsLeft >= 0">
|
||||||
v-if="!resolved && secondsLeft >= 0"
|
<span class="inline-dot">·</span>
|
||||||
class="action-timer"
|
<span class="action-timer" :class="timerClass">
|
||||||
:class="timerClass"
|
{{ formatCountdown(secondsLeft) }}
|
||||||
>
|
</span>
|
||||||
{{ formatCountdown(secondsLeft) }}
|
</template>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,22 +93,21 @@ const targetLabel = computed(() => (
|
|||||||
: props.serviceName
|
: props.serviceName
|
||||||
))
|
))
|
||||||
|
|
||||||
const titleLine = computed(() => {
|
const mainTitle = computed(() => {
|
||||||
if (!props.resolved) {
|
if (!props.resolved) {
|
||||||
return t('agentStream.mcpOAuth.waiting', { target: targetLabel.value })
|
return t('agentStream.mcpOAuth.waiting', { target: targetLabel.value })
|
||||||
}
|
}
|
||||||
if (props.authorized) {
|
return props.mcpToolName
|
||||||
return t('agentStream.mcpOAuth.resolvedAuthorized', { target: targetLabel.value })
|
? t('agentStream.mcpOAuth.titleWithTool', { service: props.serviceName, tool: props.mcpToolName })
|
||||||
}
|
: t('agentStream.mcpOAuth.titleWithService', { service: props.serviceName })
|
||||||
if (props.timedOut) return t('agentStream.mcpOAuth.resolvedTimedOut', { target: targetLabel.value })
|
|
||||||
return t('agentStream.mcpOAuth.resolvedCanceled', { target: targetLabel.value })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const cardClass = computed(() => ({
|
const statusLine = computed(() => {
|
||||||
'action-pending': !props.resolved,
|
if (!props.resolved) return t('agentStream.mcpOAuth.waitingStatus')
|
||||||
'action-success': !!props.resolved && !!props.authorized,
|
if (props.authorized) return t('agentStream.mcpOAuth.authorizedTag')
|
||||||
'action-error': !!props.resolved && !props.authorized,
|
if (props.timedOut) return t('agentStream.mcpOAuth.timedOutTag')
|
||||||
}))
|
return t('agentStream.mcpOAuth.canceledTag')
|
||||||
|
})
|
||||||
|
|
||||||
function formatCountdown(s: number): string {
|
function formatCountdown(s: number): string {
|
||||||
if (s < 60) return t('agentStream.mcpOAuth.countdownShort', { seconds: s })
|
if (s < 60) return t('agentStream.mcpOAuth.countdownShort', { seconds: s })
|
||||||
|
|||||||
@@ -1,21 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="action-card interaction-inline" :class="cardClass">
|
<div class="action-card interaction-inline" :class="{ 'action-pending': !resolved }">
|
||||||
<div class="action-header no-results">
|
<div class="action-header no-results">
|
||||||
<div class="action-title">
|
<div class="action-title">
|
||||||
<t-icon class="action-title-icon" :name="headerIcon" />
|
<t-icon class="action-title-icon" :name="headerIcon" />
|
||||||
<span class="action-name">{{ titleLine }}</span>
|
<span class="action-name">{{ mainTitle }}</span>
|
||||||
<span
|
|
||||||
v-if="!resolved && secondsLeft >= 0"
|
|
||||||
class="action-timer"
|
|
||||||
:class="timerClass"
|
|
||||||
>
|
|
||||||
{{ formatCountdown(secondsLeft) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="!resolved" class="interaction-panel">
|
<div class="interaction-status-summary">
|
||||||
<div v-if="!isJsonValid || argsDirty" class="interaction-args-meta">
|
<div class="results-summary-text">
|
||||||
|
<span v-if="resolved" class="status-label">{{ statusLine }}</span>
|
||||||
|
<span v-if="!resolved" class="inline-actions">
|
||||||
|
<button type="button" class="inline-action" :disabled="submitting" @click.stop="submit('reject')">
|
||||||
|
{{ $t('agentStream.toolApproval.reject') }}
|
||||||
|
</button>
|
||||||
|
<span class="inline-dot">·</span>
|
||||||
|
<button type="button" class="inline-action is-primary" :disabled="submitting || !isJsonValid"
|
||||||
|
@click.stop="submit('approve')">
|
||||||
|
{{ $t('agentStream.toolApproval.approve') }}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<template v-if="!resolved && secondsLeft >= 0">
|
||||||
|
<span class="inline-dot">·</span>
|
||||||
|
<span class="action-timer" :class="timerClass">
|
||||||
|
{{ formatCountdown(secondsLeft) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!resolved && !argsExpanded && (!isJsonValid || argsDirty)" class="interaction-status-summary">
|
||||||
|
<div class="results-summary-text">
|
||||||
<span v-if="!isJsonValid" class="args-status args-invalid">
|
<span v-if="!isJsonValid" class="args-status args-invalid">
|
||||||
<t-icon name="error-circle" />
|
<t-icon name="error-circle" />
|
||||||
{{ $t('agentStream.toolApproval.invalidJson') }}
|
{{ $t('agentStream.toolApproval.invalidJson') }}
|
||||||
@@ -24,37 +39,32 @@
|
|||||||
{{ $t('agentStream.toolApproval.argsModified') }}
|
{{ $t('agentStream.toolApproval.argsModified') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<t-textarea
|
</div>
|
||||||
v-model="argsText"
|
|
||||||
class="interaction-args-input"
|
<div v-if="hasArgs" class="interaction-status-summary is-clickable" @click="toggleArgs">
|
||||||
:autosize="{ minRows: 2, maxRows: 8 }"
|
<div class="results-summary-text args-toggle-row">
|
||||||
placeholder="{}"
|
<span>{{ $t('agentStream.toolApproval.argsLabel') }}</span>
|
||||||
/>
|
<t-icon class="args-toggle-icon" :name="argsExpanded ? 'chevron-down' : 'chevron-right'" />
|
||||||
<div class="interaction-panel-actions">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="inline-action"
|
|
||||||
:disabled="submitting"
|
|
||||||
@click="submit('reject')"
|
|
||||||
>
|
|
||||||
{{ $t('agentStream.toolApproval.reject') }}
|
|
||||||
</button>
|
|
||||||
<span class="inline-dot">·</span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="inline-action is-primary"
|
|
||||||
:disabled="submitting || !isJsonValid"
|
|
||||||
@click="submit('approve')"
|
|
||||||
>
|
|
||||||
{{ $t('agentStream.toolApproval.approve') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="argsText" class="interaction-panel">
|
<div v-if="hasArgs && argsExpanded" class="action-details">
|
||||||
<div class="detail-output-wrapper">
|
<div v-if="!resolved && (!isJsonValid || argsDirty)" class="interaction-args-meta">
|
||||||
<div class="detail-output">{{ argsText }}</div>
|
<span v-if="!isJsonValid" class="args-status args-invalid">
|
||||||
|
<t-icon name="error-circle" />
|
||||||
|
{{ $t('agentStream.toolApproval.invalidJson') }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="argsDirty" class="args-status args-dirty">
|
||||||
|
{{ $t('agentStream.toolApproval.argsModified') }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!resolved" class="interaction-args-block">
|
||||||
|
<t-textarea v-model="argsText" class="interaction-args-input" :autosize="{ minRows: 2, maxRows: 8 }"
|
||||||
|
placeholder="{}" @click.stop />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="interaction-args-preview">{{ argsText }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -90,10 +100,13 @@ function formatJson(raw: string): string {
|
|||||||
|
|
||||||
const initialArgs = formatJson(props.argsJson || '{}')
|
const initialArgs = formatJson(props.argsJson || '{}')
|
||||||
const argsText = ref(initialArgs)
|
const argsText = ref(initialArgs)
|
||||||
|
const argsExpanded = ref(false)
|
||||||
const submitting = ref(false)
|
const submitting = ref(false)
|
||||||
const now = ref(Date.now())
|
const now = ref(Date.now())
|
||||||
let timer: ReturnType<typeof setInterval> | null = null
|
let timer: ReturnType<typeof setInterval> | null = null
|
||||||
|
|
||||||
|
const hasArgs = computed(() => argsText.value.trim().length > 0)
|
||||||
|
|
||||||
const isJsonValid = computed(() => {
|
const isJsonValid = computed(() => {
|
||||||
if (!argsText.value.trim()) return true
|
if (!argsText.value.trim()) return true
|
||||||
try {
|
try {
|
||||||
@@ -136,17 +149,25 @@ const targetLabel = computed(() => (
|
|||||||
})
|
})
|
||||||
))
|
))
|
||||||
|
|
||||||
const titleLine = computed(() => {
|
const mainTitle = computed(() => {
|
||||||
if (!props.resolved) return t('agentStream.toolApproval.waiting', { target: targetLabel.value })
|
if (!props.resolved) {
|
||||||
if (props.approved) return t('agentStream.toolApproval.resolvedApproved', { target: targetLabel.value })
|
return t('agentStream.toolApproval.waiting', { target: targetLabel.value })
|
||||||
return t('agentStream.toolApproval.resolvedRejected', { target: targetLabel.value })
|
}
|
||||||
|
return t('agentStream.toolApproval.titleWithTarget', {
|
||||||
|
service: props.serviceName,
|
||||||
|
tool: props.mcpToolName,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const cardClass = computed(() => ({
|
const statusLine = computed(() => {
|
||||||
'action-pending': !props.resolved,
|
if (!props.resolved) return t('agentStream.toolApproval.waitingStatus')
|
||||||
'action-success': !!props.resolved && !!props.approved,
|
if (props.approved) return t('agentStream.toolApproval.approvedTag')
|
||||||
'action-error': !!props.resolved && !props.approved,
|
return t('agentStream.toolApproval.rejectedTag')
|
||||||
}))
|
})
|
||||||
|
|
||||||
|
function toggleArgs() {
|
||||||
|
argsExpanded.value = !argsExpanded.value
|
||||||
|
}
|
||||||
|
|
||||||
function formatCountdown(s: number): string {
|
function formatCountdown(s: number): string {
|
||||||
if (s < 60) return t('agentStream.toolApproval.countdownShort', { seconds: s })
|
if (s < 60) return t('agentStream.toolApproval.countdownShort', { seconds: s })
|
||||||
@@ -174,6 +195,7 @@ const submit = async (decision: 'approve' | 'reject') => {
|
|||||||
try {
|
try {
|
||||||
modified = JSON.parse(argsText.value || '{}') as Record<string, unknown>
|
modified = JSON.parse(argsText.value || '{}') as Record<string, unknown>
|
||||||
} catch {
|
} catch {
|
||||||
|
argsExpanded.value = true
|
||||||
MessagePlugin.error(t('agentStream.toolApproval.invalidJson'))
|
MessagePlugin.error(t('agentStream.toolApproval.invalidJson'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// Inline interaction rows for OAuth / tool-approval in agent stream.
|
// Inline interaction rows for OAuth / tool-approval in agent stream.
|
||||||
|
@import '../../../components/css/chat-timeline-loading.less';
|
||||||
|
|
||||||
.action-card.interaction-inline {
|
.action-card.interaction-inline {
|
||||||
gap: 0;
|
gap: 0;
|
||||||
@@ -19,13 +20,62 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
&.action-error .action-title-icon.t-icon {
|
.interaction-status-summary {
|
||||||
color: var(--td-error-color);
|
padding: 2px 0 0;
|
||||||
|
|
||||||
|
&.is-clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.results-summary-text {
|
||||||
|
color: var(--td-text-color-placeholder);
|
||||||
|
transition: color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .results-summary-text {
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.action-success .action-title-icon.t-icon {
|
.results-summary-text {
|
||||||
color: var(--td-success-color);
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: var(--agent-step-summary-size, 13px);
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-actions {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-timer {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.55;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
color: var(--td-text-color-placeholder);
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&.timer-warning {
|
||||||
|
color: var(--td-warning-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.timer-critical {
|
||||||
|
color: var(--td-error-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,12 +120,16 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
position: relative;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
row-gap: 2px;
|
row-gap: 2px;
|
||||||
|
|
||||||
.action-title-icon.t-icon {
|
.action-title-icon.t-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: -42px;
|
||||||
|
top: 3px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
@@ -99,7 +153,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action-timer {
|
.action-timer {
|
||||||
margin-left: auto;
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.55;
|
line-height: 1.55;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
@@ -117,24 +170,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.interaction-panel {
|
.interaction-args-block {
|
||||||
padding: 4px 0 0 30px;
|
padding: 4px 0 0;
|
||||||
display: flex;
|
}
|
||||||
flex-direction: column;
|
|
||||||
gap: 6px;
|
.interaction-args-preview {
|
||||||
|
padding: 4px 0 0;
|
||||||
|
font-family: var(--app-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
||||||
|
font-size: var(--agent-step-summary-size, 13px);
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
max-height: 160px;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.interaction-args-input {
|
.interaction-args-input {
|
||||||
:deep(.t-textarea__inner) {
|
:deep(.t-textarea__inner) {
|
||||||
font-family: var(--app-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
font-family: var(--app-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
||||||
font-size: 11px;
|
font-size: var(--agent-step-summary-size, 13px);
|
||||||
line-height: 1.55;
|
line-height: 1.55;
|
||||||
background: var(--td-bg-color-container);
|
background: transparent;
|
||||||
border-color: var(--td-component-stroke);
|
border: 0;
|
||||||
color: var(--td-text-color-primary);
|
box-shadow: none;
|
||||||
padding: 8px 10px;
|
color: var(--td-text-color-secondary);
|
||||||
border-radius: 6px;
|
padding: 0;
|
||||||
min-height: 48px;
|
border-radius: 0;
|
||||||
|
min-height: 36px;
|
||||||
|
resize: vertical;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,49 +210,47 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
font-size: 11px;
|
font-size: var(--agent-step-summary-size, 13px);
|
||||||
color: var(--td-text-color-placeholder);
|
color: var(--td-text-color-placeholder);
|
||||||
|
|
||||||
.args-status {
|
.args-status {
|
||||||
margin-left: auto;
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 3px;
|
gap: 3px;
|
||||||
font-size: 11px;
|
font-size: var(--agent-step-summary-size, 13px);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.args-invalid {
|
.args-status {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 3px;
|
||||||
|
font-size: var(--agent-step-summary-size, 13px);
|
||||||
|
|
||||||
|
&.args-invalid {
|
||||||
color: var(--td-error-color);
|
color: var(--td-error-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.args-dirty {
|
&.args-dirty {
|
||||||
color: var(--td-warning-color);
|
color: var(--td-warning-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-output-wrapper {
|
.action-details {
|
||||||
background: var(--td-bg-color-secondarycontainer);
|
padding: 4px 0 0;
|
||||||
border: 1px solid var(--td-component-stroke);
|
border-top: 0;
|
||||||
border-radius: 6px;
|
background: transparent;
|
||||||
overflow: hidden;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
.detail-output {
|
gap: 4px;
|
||||||
font-family: var(--app-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--td-text-color-primary);
|
|
||||||
padding: 10px 12px;
|
|
||||||
margin: 0;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-word;
|
|
||||||
line-height: 1.55;
|
|
||||||
max-height: 160px;
|
|
||||||
overflow: auto;
|
|
||||||
background: var(--td-bg-color-container);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.interaction-panel-actions {
|
.args-toggle-row {
|
||||||
display: inline-flex;
|
gap: 4px;
|
||||||
align-items: center;
|
}
|
||||||
gap: 6px;
|
|
||||||
|
.args-toggle-icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--td-text-color-placeholder);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user