fix(web): remove old "运行总览" task UI; Overview shows new template agents

The old /deployments (运行总览) + /tasks/$id pages rendered the new template agents
with meaningless old sub-task fields (待确认/sub_agile/子任务流/智能体任务图/产物/
SK快照/合并时间线 — all empty). Removed the whole old-model UI cluster and pointed
the Overview dashboard at the real new endpoint:

- deleted features/agent-console, features/agent-hub, features/tasks and the
  routes /deployments and /tasks/$id.
- cockpit (Overview) now lists deployed template agents from /api/heicode/agents
  (status counts + recent agents), not the old listAgentDeployments.
- removed the "运行总览" sidebar item + dead /deployments links in footer /
  top-nav / sidebar-config.
- routeTree regenerated; frontend build + tsc clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 17:32:03 +08:00
co-authored by Claude Opus 4.8
parent 0b2aeac51d
commit d19920d1d0
13 changed files with 55 additions and 2389 deletions
+1 -1
View File
@@ -20,7 +20,7 @@
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta name="theme-color" content="#7B6BE3" /> <meta name="theme-color" content="#7B6BE3" />
<link rel="icon" href="/favicon.ico"><script defer src="/static/js/vendor-radix.829c7e3fad.js"></script><script defer src="/static/js/vendor-tanstack.632dbe8908.js"></script><script defer src="/static/js/lib-react.5c8909c28c.js"></script><script defer src="/static/js/6374.bc21d8b214.js"></script><script defer src="/static/js/index.13c9f5d1a3.js"></script><link href="/static/css/index.592272f49e.css" rel="stylesheet"></head> <link rel="icon" href="/favicon.ico"><script defer src="/static/js/vendor-radix.829c7e3fad.js"></script><script defer src="/static/js/vendor-tanstack.632dbe8908.js"></script><script defer src="/static/js/lib-react.5c8909c28c.js"></script><script defer src="/static/js/6374.bc21d8b214.js"></script><script defer src="/static/js/index.046d6d6bc8.js"></script><link href="/static/css/index.48ece32abf.css" rel="stylesheet"></head>
<body> <body>
<div id="root"></div> <div id="root"></div>
@@ -77,7 +77,6 @@ export function Footer(props: FooterProps) {
{ {
title: t('footer.columns.docs.title'), title: t('footer.columns.docs.title'),
links: [ links: [
{ text: t('Deployments'), href: '/deployments' },
{ text: t('API Keys'), href: '/keys' }, { text: t('API Keys'), href: '/keys' },
], ],
}, },
-521
View File
@@ -1,521 +0,0 @@
import { api } from '@/lib/api'
export type AgentSubMode = 'agile' | 'waterfall'
/** Sub-agent cloud/runtime binding (passed to Agent on deploy). */
export type AgentRuntimeExecution = {
profile_id?: string
cloud_principal_refs?: string[]
network_policy_ref?: string
}
/** SK allow/deny policy attached to the agent in the deployment plan. */
export type AgentSKAccessPolicy = {
policy_ref?: string
deny_skill_ids?: string[]
inherit_deployment_defaults?: boolean
}
/** Git-backed SK source (`type: git`). */
export type AgentRepoRef = {
connection_id?: string
repo_url?: string
ref: string
paths: string[]
}
/** Single SK source entry (git or upload). */
export type AgentSKSource = {
type?: string
artifact_id?: string
mime?: string
repo_ref?: AgentRepoRef
}
export type AgentAgentPlan = {
role_template: string
goal: string
default_model_id?: string
sk_sources?: AgentSKSource[]
runtime_execution?: AgentRuntimeExecution
sk_access_policy?: AgentSKAccessPolicy
resource_grants?: Array<{
grant_id?: string
resource_id?: string
resource_type?: string
user_id?: string
binding_scope?: string
target_role?: string
target_agent_ref?: string
permission_scope?: string[]
constraints?: Record<string, string>
metadata?: Record<string, string>
status?: 'pending' | 'active' | 'disabled' | 'revoked'
secret_ref?: string
audit?: Record<string, string>
}>
}
export type AgentBudget = {
max_tokens: number
max_cost_usd: number
max_duration_sec: number
}
export type AgentUserContext = {
user_id: string
email?: string
role?: string
channel_id?: string
subscription_tier?: string
}
export type AgentBillingContext = {
provider?: 'newapi'
newapi_user_ref?: string
newapi_group?: string
quota_ref?: string
}
export type AgentAgentRuntime = {
platform?: 'agent'
agents?: Array<{
role: string
model_ref: string
instance_count: number
}>
}
export type AgentConstraints = {
/** Runtime model allow-list for Agent deployments; not a NewAPI billing map. */
allowed_model_ids?: string[]
}
export type AgentOrchestrationMetadata = {
/**
* Compatibility field for Agent routing scope; UI treats this as user scope,
* not billing tenant.
*/
tenant_id: string
/**
* Compatibility field for Agent routing scope; UI treats this as resource
* scope, not project control.
*/
project_id: string
correlation_id: string
}
export type AgentOrchestrationPlan = {
intent_id: string
template_hint: string
objective: string
sub_mode?: AgentSubMode
risk_level: 'low' | 'medium' | 'high'
budget: AgentBudget
user_context: AgentUserContext
billing_context?: AgentBillingContext
agent_runtime?: AgentAgentRuntime
agents: AgentAgentPlan[]
constraints: AgentConstraints
metadata: AgentOrchestrationMetadata
}
export type AgentCreateDeploymentBody = {
orchestration_plan: AgentOrchestrationPlan
}
export type AgentCreateDeploymentResult = {
deployment_id: string
sub_mode?: AgentSubMode
status: string
agent_instances?: Array<{
instance_id?: string
role?: string
phase?: string
}>
permission_manifest?: AgentPermissionManifest
}
export type AgentPermissionManifest = {
user_id?: string
binding_scope?: string
agent_role?: string
target_agent_ref?: string
resource_grants?: Array<{
grant_id?: string
resource_id?: string
resource_type?: string
resource_ref?: string
allowed_actions?: string[]
constraints?: Record<string, string>
secret_ref?: string
status?: string
}>
}
export type AgentDeployment = {
deployment_id: string
// Client-facing mode (sub_agile | swarm) + Manager-judged display_status,
// both populated by the backend list/detail responses.
mode?: string
display_status?: string
sub_mode?: AgentSubMode
status: string
phase: string
runtime_state?: string
runtime_deployment_id?: string
runtime_swarm_id?: string
runtime_last_sync_at?: string
failure_reason?: string
created_at: string
updated_at: string
permission_manifest?: AgentPermissionManifest
orchestration_plan: {
intent_id?: string
template_hint?: string
objective?: string
sub_mode?: AgentSubMode
risk_level?: string
budget?: AgentBudget
agents?: AgentAgentPlan[]
constraints?: AgentConstraints
metadata?: AgentOrchestrationMetadata
}
}
export type AgentRuntimeDiagnostics = {
deployment_id: string
runtime_mode?: 'agent' | 'swarm' | string
sub_mode?: AgentSubMode
runtime_deployment_id?: string
runtime_swarm_id?: string
data_source?: string
http_status?: number
status?: string
phase?: string
progress?: unknown
error_message?: string
agents?: Array<Record<string, unknown>>
artifacts?: Array<Record<string, unknown>>
metrics?: Record<string, unknown>
warnings?: string[]
checked_at?: string
}
export type AgentApprovalRequest = {
approval_id: string
user_id: number
deployment_id?: string
binding_scope?: string
operation: string
resource_id: string
resource_type: string
resource_scope?: string
target_role: string
risk_level: 'low' | 'medium' | 'high' | 'critical'
requires_credential: boolean
credential_lease_id?: string
status: 'pending' | 'approved' | 'rejected' | 'expired'
requested_by?: string
decided_by?: string
request_reason?: string
decision_reason?: string
ttl_seconds: number
expires_at: number
decided_at?: number
created_at?: number
updated_at?: number
credential_lease?: AgentCredentialLease
}
export type AgentCredentialLease = {
lease_id: string
credential_ref: string
approval_id: string
user_id: number
deployment_id?: string
binding_scope?: string
resource_id: string
resource_type: string
resource_scope?: string
target_role: string
status: 'active' | 'expired' | 'revoked'
ttl_seconds: number
expires_at: number
revoked_at?: number
created_at?: number
updated_at?: number
}
type ApiEnvelope<T> = { success: boolean; data?: T; message?: string }
export type GitSourceUsage = 'project' | 'sk' | 'combined'
export type GitSource = {
id: number
user_id: number
tenant_id?: string
name: string
provider: string
repo_url: string
ref: string
paths: string[]
usage: GitSourceUsage | string
status: string
created_at?: number
updated_at?: number
}
export type GitSourcePayload = {
tenant_id?: string
name: string
provider: string
repo_url: string
ref: string
paths: string[]
usage: GitSourceUsage
}
// Platform-recommended role catalog shape. Mirrors backend
// `AgentRoleTemplate` in controller/agent_role_template.go. The
// six canonical roles come from docs/product-package §13.3.3 —
// keys are stable identifiers, display strings can be translated.
export type AgentRoleTemplate = {
key: string
display_name: string
summary: string
default_model: string
default_permissions: string[]
risk_level: 'low' | 'medium' | 'high'
}
// Cached at module level — the canonical six-role catalog doesn't
// change between page loads, so we avoid an extra request every
// time the create-deployment sheet opens.
let _roleTemplateCache: AgentRoleTemplate[] | null = null
export async function listAgentRoleTemplates(): Promise<AgentRoleTemplate[]> {
if (_roleTemplateCache) return _roleTemplateCache
const res = await api.get<ApiEnvelope<{ items?: AgentRoleTemplate[] }>>(
'/api/agent/role-templates'
)
const items = res.data?.data?.items ?? []
if (items.length > 0) {
_roleTemplateCache = items
}
return items
}
export async function listAgentDeployments(): Promise<AgentDeployment[]> {
const res = await api.get<ApiEnvelope<{ items?: AgentDeployment[] }>>(
'/api/agent/user/deployments'
)
return res.data?.data?.items ?? []
}
export async function listAgentDeploymentsQuiet(): Promise<AgentDeployment[]> {
const res = await api.get<ApiEnvelope<{ items?: AgentDeployment[] }>>(
'/api/agent/user/deployments',
{
skipBusinessError: true,
skipErrorHandler: true,
} as Record<string, unknown>
)
if (!res.data?.success) return []
return res.data?.data?.items ?? []
}
export async function createAgentDeployment(
body: AgentCreateDeploymentBody
): Promise<AgentCreateDeploymentResult> {
const res = await api.post<ApiEnvelope<AgentCreateDeploymentResult>>(
'/api/agent/user/deployments',
body
)
const env = res.data
if (!env?.success) {
throw new Error(env?.message || 'Deployment request failed')
}
const data = env.data
if (!data?.deployment_id) {
throw new Error(env?.message || 'Invalid deployment response')
}
return data
}
export async function getAgentDeploymentEvents(deploymentId: string) {
const res = await api.get<
ApiEnvelope<{ items?: Array<Record<string, unknown>> }>
>(`/api/agent/user/deployments/${deploymentId}/events`)
return res.data?.data?.items ?? []
}
export async function getAgentDeploymentArtifacts(deploymentId: string) {
const res = await api.get<
ApiEnvelope<{ items?: Array<Record<string, unknown>> }>
>(`/api/agent/user/deployments/${deploymentId}/artifacts`)
return res.data?.data?.items ?? []
}
export async function getAgentDeploymentSKSnapshots(deploymentId: string) {
const res = await api.get<
ApiEnvelope<{ items?: Array<Record<string, unknown>> }>
>(`/api/agent/user/deployments/${deploymentId}/sk-snapshots`)
return res.data?.data?.items ?? []
}
export async function getAgentDeploymentTimeline(deploymentId: string) {
const res = await api.get<
ApiEnvelope<{
callbacks?: Array<Record<string, unknown>>
artifacts?: Array<Record<string, unknown>>
sk_snapshots?: Array<Record<string, unknown>>
timeline?: Array<Record<string, unknown>>
}>
>(`/api/agent/user/deployments/${deploymentId}/timeline`)
return (
res.data?.data ?? {
callbacks: [],
artifacts: [],
sk_snapshots: [],
timeline: [],
}
)
}
export async function getAgentRuntimeDiagnostics(
deploymentId: string
): Promise<AgentRuntimeDiagnostics | null> {
const res = await api.get<ApiEnvelope<AgentRuntimeDiagnostics>>(
`/api/agent/user/deployments/${deploymentId}/runtime-diagnostics`,
{
skipBusinessError: true,
skipErrorHandler: true,
} as Record<string, unknown>
)
if (!res.data?.success) return null
return res.data?.data ?? null
}
export async function simulateAgentDeploymentEvents(
deploymentId: string,
events?: string[]
): Promise<{ deployment_id: string; simulated: boolean; total: number }> {
const res = await api.post<
ApiEnvelope<{ deployment_id: string; simulated: boolean; total: number }>
>(`/api/agent/user/deployments/${deploymentId}/simulate-events`, {
events: events ?? [],
})
const env = res.data
if (!env?.success || !env.data) {
throw new Error(env?.message || 'simulateAgentDeploymentEvents failed')
}
return env.data
}
export async function getAgentAuditLogs() {
const res = await api.get<
ApiEnvelope<{ items?: Array<Record<string, unknown>> }>
>('/api/agent/audit-logs')
return res.data?.data?.items ?? []
}
export async function listAgentApprovals(params?: {
status?: string
deployment_id?: string
}): Promise<AgentApprovalRequest[]> {
const res = await api.get<ApiEnvelope<{ items?: AgentApprovalRequest[] }>>(
'/api/agent/approvals',
{ params }
)
return res.data?.data?.items ?? []
}
export async function approveAgentApproval(
approvalId: string,
reason?: string
): Promise<AgentApprovalRequest> {
const res = await api.post<ApiEnvelope<AgentApprovalRequest>>(
`/api/agent/approvals/${approvalId}/approve`,
{ reason }
)
if (!res.data?.success || !res.data.data) {
throw new Error(res.data?.message || 'Approve request failed')
}
return res.data.data
}
export async function rejectAgentApproval(
approvalId: string,
reason?: string
): Promise<AgentApprovalRequest> {
const res = await api.post<ApiEnvelope<AgentApprovalRequest>>(
`/api/agent/approvals/${approvalId}/reject`,
{ reason }
)
if (!res.data?.success || !res.data.data) {
throw new Error(res.data?.message || 'Reject request failed')
}
return res.data.data
}
export async function listAgentCredentialLeases(params?: {
status?: string
deployment_id?: string
}): Promise<AgentCredentialLease[]> {
const res = await api.get<ApiEnvelope<{ items?: AgentCredentialLease[] }>>(
'/api/agent/credential-leases',
{ params }
)
return res.data?.data?.items ?? []
}
export async function revokeAgentCredentialLease(
leaseId: string,
reason?: string
): Promise<AgentCredentialLease> {
const res = await api.post<ApiEnvelope<AgentCredentialLease>>(
`/api/agent/credential-leases/${leaseId}/revoke`,
{ reason }
)
if (!res.data?.success || !res.data.data) {
throw new Error(res.data?.message || 'Revoke lease failed')
}
return res.data.data
}
export async function getAgentSnapshots(deploymentId: string) {
const res = await api.get<
ApiEnvelope<{ items?: Array<Record<string, unknown>> }>
>(`/api/agent/deployments/${deploymentId}/sk-snapshots`, {
skipBusinessError: true,
skipErrorHandler: true,
} as Record<string, unknown>)
if (!res.data?.success) return []
return res.data?.data?.items ?? []
}
export async function listGitSources(): Promise<GitSource[]> {
const res =
await api.get<ApiEnvelope<{ items?: GitSource[] }>>('/api/git-sources/')
return res.data?.data?.items ?? []
}
export async function createGitSource(
body: GitSourcePayload
): Promise<GitSource> {
const res = await api.post<ApiEnvelope<GitSource>>('/api/git-sources/', body)
if (!res.data?.success || !res.data.data) {
throw new Error(res.data?.message || 'Create Git source failed')
}
return res.data.data
}
export async function deleteGitSource(id: number): Promise<void> {
const res = await api.delete<ApiEnvelope<{ deleted?: boolean }>>(
`/api/git-sources/${id}`
)
if (!res.data?.success) {
throw new Error(res.data?.message || 'Delete Git source failed')
}
}
File diff suppressed because it is too large Load Diff
-34
View File
@@ -1,34 +0,0 @@
import { Link } from '@tanstack/react-router'
type AgentHubProps = {
title: string
description: string
}
const quickLinks = [{ title: 'Deployments', to: '/deployments' as const }]
export function AgentHub(props: AgentHubProps) {
return (
<div className='mx-auto w-full max-w-5xl p-6'>
<div className='mb-5'>
<h1 className='text-2xl font-semibold'>{props.title}</h1>
<p className='text-muted-foreground mt-2 text-sm'>{props.description}</p>
</div>
<div className='grid gap-4 md:grid-cols-3'>
{quickLinks.map((item) => (
<Link
key={item.title}
to={item.to}
className='bg-card hover:bg-accent/40 rounded-lg border p-4 transition-colors'
>
<div className='font-medium'>{item.title}</div>
<div className='text-muted-foreground mt-1 text-xs'>
Open {item.title.toLowerCase()} workspace
</div>
</Link>
))}
</div>
</div>
)
}
@@ -15,13 +15,26 @@ import {
import { api } from '@/lib/api' import { api } from '@/lib/api'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import {
listAgentDeployments,
type AgentDeployment,
} from '@/features/agent-console/api'
import { WalletStatsCard } from '@/features/wallet/components/wallet-stats-card' import { WalletStatsCard } from '@/features/wallet/components/wallet-stats-card'
import type { UserWalletData } from '@/features/wallet/types' import type { UserWalletData } from '@/features/wallet/types'
// Deployed template agents (new model).
type AgentItem = {
agent_id: string
template_id: string
subdomain: string
status: string
created_at: string
updated_at: string
}
async function listMyAgents(): Promise<AgentItem[]> {
const res = await api.get<{ data?: { items?: AgentItem[] } }>(
'/api/heicode/agents'
)
return res.data?.data?.items ?? []
}
// Current user's OWN balance/usage (NOT the admin-global aggregate) — same // Current user's OWN balance/usage (NOT the admin-global aggregate) — same
// source the 模型与余额 page uses. // source the 模型与余额 page uses.
async function getSelfUsage(): Promise<UserWalletData> { async function getSelfUsage(): Promise<UserWalletData> {
@@ -149,9 +162,10 @@ export function CockpitView() {
const { t } = useTranslation() const { t } = useTranslation()
const deploymentsQuery = useQuery({ const deploymentsQuery = useQuery({
queryKey: ['cockpit', 'deployments'], queryKey: ['cockpit', 'agents'],
queryFn: listAgentDeployments, queryFn: listMyAgents,
refetchInterval: 30_000, refetchInterval: 30_000,
retry: false,
}) })
const selfQuery = useQuery({ const selfQuery = useQuery({
@@ -162,7 +176,7 @@ export function CockpitView() {
}) })
const stats = useMemo(() => { const stats = useMemo(() => {
const list: AgentDeployment[] = deploymentsQuery.data ?? [] const list: AgentItem[] = deploymentsQuery.data ?? []
const counters: Record<StatusKey, number> = { const counters: Record<StatusKey, number> = {
running: 0, running: 0,
success: 0, success: 0,
@@ -170,7 +184,7 @@ export function CockpitView() {
pending: 0, pending: 0,
} }
list.forEach((d) => { list.forEach((d) => {
counters[classifyStatus(d.display_status || d.status || '')]++ counters[classifyStatus(d.status || '')]++
}) })
const total = list.length || 1 const total = list.length || 1
const successRate = Math.round( const successRate = Math.round(
@@ -254,7 +268,7 @@ export function CockpitView() {
</h3> </h3>
</div> </div>
<Button asChild size='sm' variant='ghost' className='gap-1'> <Button asChild size='sm' variant='ghost' className='gap-1'>
<Link to='/deployments'> <Link to='/deploy-agent'>
{t('Open Deployments')} {t('Open Deployments')}
<ArrowUpRight className='h-3.5 w-3.5' /> <ArrowUpRight className='h-3.5 w-3.5' />
</Link> </Link>
@@ -276,47 +290,38 @@ export function CockpitView() {
</div> </div>
) : ( ) : (
<ul className='space-y-2'> <ul className='space-y-2'>
{recentDeployments.map((dep) => { {recentDeployments.map((dep) => (
const tenant = dep.orchestration_plan?.metadata?.tenant_id || '—' <li
const objective = key={dep.agent_id}
dep.orchestration_plan?.objective || className='group flex items-center justify-between gap-4 rounded-xl border border-[color-mix(in_oklch,var(--primary)_18%,var(--border))] bg-[color-mix(in_oklch,var(--card)_55%,transparent)] p-3 transition hover:border-primary/45'
dep.orchestration_plan?.template_hint || >
t('No objective') <div className='min-w-0 flex-1'>
return ( <div className='flex items-center gap-2'>
<li <Rocket className='h-3.5 w-3.5 text-primary' />
key={dep.deployment_id} <span className='truncate text-sm font-medium'>
className='group flex items-center justify-between gap-4 rounded-xl border border-[color-mix(in_oklch,var(--primary)_18%,var(--border))] bg-[color-mix(in_oklch,var(--card)_55%,transparent)] p-3 transition hover:border-primary/45' {dep.template_id}
> </span>
<div className='min-w-0 flex-1'> <PhasePill phase={dep.status} />
<div className='flex items-center gap-2'>
<Rocket className='h-3.5 w-3.5 text-primary' />
<span className='truncate font-mono text-xs'>
{dep.deployment_id}
</span>
<PhasePill phase={dep.phase || dep.status} />
</div>
<p className='mt-1 truncate text-sm text-foreground/90'>
{objective}
</p>
<p className='mt-0.5 truncate text-[11px] text-muted-foreground'>
<Building2 className='mr-1 inline h-3 w-3' />
{tenant} · {formatRelative(dep.updated_at || dep.created_at)} ago
</p>
</div> </div>
<Button <p className='mt-0.5 truncate text-[11px] text-muted-foreground'>
asChild <Building2 className='mr-1 inline h-3 w-3' />
size='sm' {dep.subdomain || '—'} ·{' '}
variant='outline' {formatRelative(dep.updated_at || dep.created_at)} ago
className='shrink-0 opacity-70 group-hover:opacity-100' </p>
> </div>
<Link to='/deployments'> <Button
<ScrollText className='mr-1 h-3.5 w-3.5' /> asChild
{t('Inspect')} size='sm'
</Link> variant='outline'
</Button> className='shrink-0 opacity-70 group-hover:opacity-100'
</li> >
) <Link to='/deploy-agent'>
})} <ScrollText className='mr-1 h-3.5 w-3.5' />
{t('Inspect')}
</Link>
</Button>
</li>
))}
</ul> </ul>
)} )}
</section> </section>
@@ -1,519 +0,0 @@
/**
* Task Card route — implements docs/product-package/10 §"任务卡" + 11 §3
* 任务卡 wireframe, backed by mcp-server §6 HeicodeTask object:
*
* - status = "configuring" → render the open follow-up questions
* (each option becomes a clickable chip; clicking POSTs answer to
* /api/user/tasks/$id/answer and the backend state machine advances).
* - status = "running" / etc → render task.card with the four blocks
* the spec mandates: 目标 / 第一版范围 / 自动生成 / 待确认上下文.
*
* Forbidden per §10 高级展开: no JSON editor, no permission manifest, no
* resource_grant editor. Only the user-facing summary fields.
*/
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Link, getRouteApi } from '@tanstack/react-router'
import {
ArrowLeft,
CheckCircle2,
CircleDashed,
GitBranch,
ListChecks,
MessageSquare,
PencilLine,
PlayCircle,
Rocket,
ScrollText,
ShieldCheck,
Sparkles,
Wallet,
XCircle,
} from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
import {
answerHeicodeTask,
createDeploymentDraftFromHeicodeTask,
getHeicodeTask,
type HeicodeFollowup,
type HeicodeManagerAction,
type HeicodeTask,
type HeicodeTaskStatus,
} from '@/lib/heicode-mcp'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import {
createAgentDeployment,
type AgentOrchestrationPlan,
} from '@/features/agent-console/api'
const route = getRouteApi('/_authenticated/tasks/$id')
type StatusKey = 'running' | 'success' | 'failed' | 'pending'
const STATUS_MAP: Record<HeicodeTaskStatus | string, StatusKey> = {
draft: 'pending',
configuring: 'pending',
awaiting_approval: 'pending',
running: 'running',
paused: 'pending',
completed: 'success',
failed: 'failed',
}
function classifyStatus(s: string): StatusKey {
return STATUS_MAP[s] ?? 'pending'
}
function StatusBadge({ status }: { status: HeicodeTaskStatus | string }) {
const k = classifyStatus(status)
const map: Record<StatusKey, { cls: string; Icon: typeof PlayCircle }> = {
running: {
cls: 'bg-[color-mix(in_oklch,var(--primary)_22%,transparent)] text-primary ring-primary/40',
Icon: PlayCircle,
},
success: {
cls: 'bg-emerald-500/15 text-emerald-400 ring-emerald-500/30',
Icon: CheckCircle2,
},
failed: {
cls: 'bg-rose-500/15 text-rose-400 ring-rose-500/30',
Icon: XCircle,
},
pending: {
cls: 'bg-amber-500/15 text-amber-400 ring-amber-500/30',
Icon: CircleDashed,
},
}
const p = map[k]
return (
<span
className={cn(
'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold tracking-[0.12em] uppercase ring-1 ring-inset',
p.cls
)}
>
<p.Icon className='h-3 w-3' />
{status}
</span>
)
}
function readScopeArray(card: HeicodeTask['card'], key: string): string[] {
if (!card) return []
const v = (card as Record<string, unknown>)[key]
if (Array.isArray(v))
return v.filter((x): x is string => typeof x === 'string')
if (typeof v === 'string' && v.trim()) return [v]
return []
}
function readManagerActions(card: HeicodeTask['card']): HeicodeManagerAction[] {
if (!card) return []
const v = (card as Record<string, unknown>).manager_actions
if (!Array.isArray(v)) return []
return v
.filter(
(x): x is HeicodeManagerAction =>
typeof x === 'object' &&
x != null &&
typeof (x as Record<string, unknown>).label === 'string' &&
typeof (x as Record<string, unknown>).deeplink === 'string'
)
.slice(0, 6)
}
/** Resolve helper icon for a manager action by deeplink keyword. */
function iconForAction(deeplink: string): typeof GitBranch {
const k = deeplink.toLowerCase()
if (
k.includes('resource') ||
k.includes('preparation') ||
k.includes('sk-source')
)
return GitBranch
if (k.includes('audit')) return ShieldCheck
if (k.includes('wallet') || k.includes('budget')) return Wallet
if (k.includes('event') || k.includes('activity')) return ScrollText
return Rocket
}
/** Manager-side route normalization. Legacy deep-links from older mcp-server
* payloads (resources / team / audit) now collapse to the live task overview;
* wallet keeps its own route. */
function normalizeDeeplink(deeplink: string): string {
return deeplink
.replace(/^\/manager\/resources/i, '/deployments')
.replace(/^\/manager\/team/i, '/deployments')
.replace(/^\/manager\/audit/i, '/deployments')
.replace(/^\/manager\/wallet/i, '/wallet')
.replace(/^\/manager\//i, '/')
}
/** Collect open follow-ups from the most recent Heicode thread entry. */
function collectOpenFollowups(task: HeicodeTask): HeicodeFollowup[] {
for (let i = task.thread.length - 1; i >= 0; i--) {
const entry = task.thread[i]!
if (
entry.kind === 'heicode' &&
entry.followups &&
entry.followups.length > 0
) {
return entry.followups
}
}
return []
}
export function TaskCardView() {
const { t } = useTranslation()
const { id } = route.useParams()
const queryClient = useQueryClient()
const { data: task, isLoading } = useQuery({
queryKey: ['heicode', 'task', id],
queryFn: () => getHeicodeTask(id),
refetchInterval: (q) => {
const status = (q.state.data as HeicodeTask | undefined)?.status
if (status === 'completed' || status === 'failed') return false
if (status === 'running' || status === 'awaiting_approval') return 3_000
return 15_000
},
})
const answerMutation = useMutation({
mutationFn: ({ qid, oid }: { qid: string; oid: string }) =>
answerHeicodeTask(id, qid, oid),
onSuccess: (updated) => {
queryClient.setQueryData(['heicode', 'task', id], updated)
void queryClient.invalidateQueries({
queryKey: ['heicode', 'tasks', 'recent'],
})
if (updated.status === 'running') {
toast.success(
t(
'All follow-ups answered. Heicode generated the recommendation summary.'
)
)
}
},
onError: (err) => {
toast.error(
err instanceof Error ? err.message : t('Failed to answer follow-up')
)
},
})
const deploymentMutation = useMutation({
mutationFn: async () => {
if (!task) throw new Error('Task not found')
const draft = await createDeploymentDraftFromHeicodeTask(task, {
sub_mode: 'agile',
binding_scope: `task-${task.id}`,
role_templates: ['backend'],
default_model_id: 'claude-sonnet-4-6',
})
return createAgentDeployment({
orchestration_plan:
draft.orchestration_plan as unknown as AgentOrchestrationPlan,
})
},
onSuccess: (deployment) => {
void queryClient.invalidateQueries({ queryKey: ['agent', 'deployments'] })
toast.success(
t('Manager deployment created', {
deployment_id: deployment.deployment_id,
}) as string
)
},
onError: (err) => {
toast.error(
err instanceof Error ? err.message : t('Deployment request failed')
)
},
})
if (isLoading) {
return (
<div className='mx-auto max-w-3xl space-y-4 p-6'>
<Skeleton className='h-7 w-40' />
<Skeleton className='h-48 w-full rounded-2xl' />
<Skeleton className='h-32 w-full rounded-2xl' />
</div>
)
}
if (!task) {
return (
<div className='mx-auto max-w-3xl space-y-4 p-6'>
<Button asChild variant='ghost' size='sm' className='gap-1'>
<Link to='/dashboard/$section' params={{ section: 'overview' }}>
<ArrowLeft className='h-4 w-4' />
{t('Back to home')}
</Link>
</Button>
<div className='rounded-2xl border border-dashed border-[color-mix(in_oklch,var(--primary)_22%,var(--border))] p-10 text-center'>
<p className='text-muted-foreground text-sm'>
{t(
'Task not found. It may have been removed or was never created.'
)}
</p>
</div>
</div>
)
}
const openFollowups = collectOpenFollowups(task)
// Card shape per live mcp-server smoke test (§6.4 returns):
// { goal: string, scope: string[], generated_artifacts: string[],
// manager_actions: Array<{label, deeplink}> }
const objective =
(task.card &&
((task.card as Record<string, unknown>).goal as string | undefined)) ||
task.name ||
task.intent ||
t('No objective')
const firstVersionScope =
readScopeArray(task.card, 'scope').length > 0
? readScopeArray(task.card, 'scope')
: [task.intent || objective]
const autoGenerated =
readScopeArray(task.card, 'generated_artifacts').length > 0
? readScopeArray(task.card, 'generated_artifacts')
: [
t('Product brief'),
t('Prototype description'),
t('Development tasks'),
t('Check list'),
t('Deployment steps'),
]
const managerActions = readManagerActions(task.card)
const pendingContextLine = t(
'Code, docs, cloud resources and high-risk approval rules. Connect them in the preparation checklist.'
)
return (
<div className='mx-auto max-w-4xl space-y-5 p-6'>
<header className='flex items-center justify-between gap-3'>
<Button asChild variant='ghost' size='sm' className='gap-1'>
<Link to='/dashboard/$section' params={{ section: 'overview' }}>
<ArrowLeft className='h-4 w-4' />
{t('Back to home')}
</Link>
</Button>
<span className='text-muted-foreground font-mono text-[11px]'>
{task.id}
</span>
</header>
{/* ── Follow-up questions (only while status=configuring) ─────────── */}
{task.status === 'configuring' && openFollowups.length > 0 && (
<section
className='overflow-hidden rounded-3xl border p-5 sm:p-6'
style={{
borderColor: 'rgba(123,107,227,0.28)',
backgroundImage:
'linear-gradient(180deg, rgba(123,107,227,0.07) 0%, rgba(123,107,227,0.00) 60%)',
}}
>
<div className='flex items-start gap-3'>
<span
className='inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-2xl text-white'
style={{ backgroundImage: 'var(--gradient-brand)' }}
>
<MessageSquare className='h-4 w-4' />
</span>
<div className='min-w-0 flex-1'>
<p className='text-muted-foreground text-[11px] font-semibold tracking-[0.16em] uppercase'>
{t('Heicode is asking')}
</p>
<p className='text-foreground mt-1 text-sm'>
{task.status_caption ||
t(
'Answer a few questions so Heicode can draft the right plan.'
)}
</p>
</div>
</div>
<ol className='mt-5 space-y-4'>
{openFollowups.map((q) => (
<li
key={q.id}
className='bg-background/40 rounded-2xl border border-[color-mix(in_oklch,var(--primary)_18%,var(--border))] p-4'
>
<p className='text-sm font-medium'>{q.question}</p>
<div className='mt-3 flex flex-wrap gap-2'>
{q.options.map((opt) => (
<Button
key={opt.id}
type='button'
size='sm'
variant='outline'
disabled={answerMutation.isPending}
onClick={() =>
answerMutation.mutate({ qid: q.id, oid: opt.id })
}
className={cn(
'rounded-xl text-xs',
opt.risk === 'high-risk' &&
'border-rose-500/40 text-rose-300 hover:border-rose-500/70'
)}
>
{opt.label}
{opt.risk === 'high-risk' && (
<span className='ms-1 rounded-full bg-rose-500/15 px-1.5 text-[9px] tracking-wider text-rose-300 uppercase'>
{t('high-risk')}
</span>
)}
</Button>
))}
</div>
</li>
))}
</ol>
</section>
)}
{/* ── Task card (objective / scope / auto / pending) ───────────── */}
<section
className='overflow-hidden rounded-3xl border p-6 sm:p-8'
style={{
borderColor: 'rgba(123,107,227,0.28)',
backgroundImage:
'radial-gradient(circle at 0% 0%, rgba(184,136,229,0.10), transparent 60%), linear-gradient(180deg, rgba(123,107,227,0.04) 0%, rgba(123,107,227,0.00) 60%)',
}}
>
<div className='flex items-start justify-between gap-4'>
<div className='min-w-0 flex-1'>
<p className='text-muted-foreground text-[11px] font-semibold tracking-[0.16em] uppercase'>
{t('Task card')}
</p>
<h1 className='mt-2 text-2xl font-semibold tracking-tight sm:text-3xl'>
{objective}
</h1>
{task.intent && task.intent !== objective && (
<p className='text-muted-foreground mt-2 text-sm'>
{task.intent}
</p>
)}
</div>
<StatusBadge status={task.status} />
</div>
<div className='mt-6 grid gap-5 md:grid-cols-2'>
<div className='bg-background/40 rounded-2xl border border-[color-mix(in_oklch,var(--primary)_18%,var(--border))] p-4'>
<p className='flex items-center gap-1.5 text-sm font-semibold'>
<ListChecks className='text-primary h-4 w-4' />
{t('First-version scope')}
</p>
<ul className='text-muted-foreground mt-2 space-y-1.5 text-sm'>
{firstVersionScope.map((line, i) => (
<li key={i} className='flex items-start gap-2'>
<span className='bg-primary mt-1.5 inline-block h-1 w-1 shrink-0 rounded-full' />
<span>{line}</span>
</li>
))}
</ul>
</div>
<div className='bg-background/40 rounded-2xl border border-[color-mix(in_oklch,var(--primary)_18%,var(--border))] p-4'>
<p className='flex items-center gap-1.5 text-sm font-semibold'>
<Sparkles className='text-primary h-4 w-4' />
{t('Heicode auto-generates')}
</p>
<p className='text-muted-foreground mt-2 text-sm'>
{autoGenerated.join(' / ')}
</p>
<p className='text-muted-foreground mt-2 text-[11px]'>
{t(
'These artifacts appear inside the desktop client as the task progresses.'
)}
</p>
</div>
</div>
<div className='bg-background/30 mt-5 rounded-2xl border border-dashed border-[color-mix(in_oklch,var(--primary)_22%,var(--border))] p-4'>
<p className='text-muted-foreground text-[11px] font-semibold tracking-[0.14em] uppercase'>
{t('Needs Manager assistance')}
</p>
<div className='mt-3 flex flex-wrap gap-2'>
{managerActions.length > 0 ? (
managerActions.map((act) => {
const Icon = iconForAction(act.deeplink)
const to = normalizeDeeplink(act.deeplink).split('?')[0]
return (
<Button
key={`${act.label}-${act.deeplink}`}
asChild
size='sm'
variant='outline'
className='rounded-xl'
>
<a href={to}>
<Icon className='mr-1 h-3.5 w-3.5' />
{act.label}
</a>
</Button>
)
})
) : (
<Button
asChild
size='sm'
variant='outline'
className='rounded-xl'
>
<Link to='/wallet'>
<Wallet className='mr-1 h-3.5 w-3.5' />
{t('Budget & usage')}
</Link>
</Button>
)}
</div>
</div>
<footer className='mt-6 flex flex-wrap items-center justify-between gap-3 border-t border-dashed border-[color-mix(in_oklch,var(--primary)_18%,var(--border))] pt-4'>
<Button
variant='ghost'
size='sm'
className='text-muted-foreground gap-1'
disabled
title={t('Editing the objective happens in the desktop client.')}
>
<PencilLine className='h-3.5 w-3.5' />
{t('Edit objective in desktop client')}
</Button>
<Button
type='button'
variant='outline'
size='sm'
className='gap-1 rounded-xl'
disabled={
deploymentMutation.isPending ||
task.status === 'failed' ||
task.status === 'draft' ||
task.status === 'configuring'
}
onClick={() => deploymentMutation.mutate()}
>
<Rocket className='h-3.5 w-3.5' />
{deploymentMutation.isPending
? t('Creating deployment')
: t('Create Manager deployment')}
</Button>
</footer>
</section>
<section className='rounded-2xl border border-[color-mix(in_oklch,var(--primary)_18%,var(--border))] bg-[color-mix(in_oklch,var(--card)_55%,transparent)] p-4'>
<p className='text-muted-foreground text-[11px] font-semibold tracking-[0.16em] uppercase'>
{t('Pending context')}
</p>
<p className='text-muted-foreground mt-2 text-sm'>
{pendingContextLine}
</p>
</section>
</div>
)
}
-1
View File
@@ -40,7 +40,6 @@ const DEFAULT_SIDEBAR_MODULES: SidebarModulesAdminConfig = {
const URL_TO_CONFIG_MAP: Record<string, { section: string; module: string }> = { const URL_TO_CONFIG_MAP: Record<string, { section: string; module: string }> = {
'/dashboard': { section: 'cockpit', module: 'overview' }, '/dashboard': { section: 'cockpit', module: 'overview' },
'/dashboard/overview': { section: 'cockpit', module: 'overview' }, '/dashboard/overview': { section: 'cockpit', module: 'overview' },
'/deployments': { section: 'cockpit', module: 'deployments' },
'/users': { section: 'admin', module: 'tenants' }, '/users': { section: 'admin', module: 'tenants' },
'/system-settings/general': { section: 'admin', module: 'settings' }, '/system-settings/general': { section: 'admin', module: 'settings' },
'/system-settings': { section: 'admin', module: 'settings' }, '/system-settings': { section: 'admin', module: 'settings' },
-6
View File
@@ -4,7 +4,6 @@ import {
Download, Download,
GitBranch, GitBranch,
LayoutDashboard, LayoutDashboard,
Rocket,
Settings, Settings,
Smartphone, Smartphone,
UserCog, UserCog,
@@ -58,11 +57,6 @@ export function useSidebarData(): SidebarData {
url: '/deploy-agent', url: '/deploy-agent',
icon: Bot, icon: Bot,
}, },
{
title: t('Agent runs'),
url: '/deployments',
icon: Rocket,
},
], ],
}, },
-3
View File
@@ -63,8 +63,5 @@ export function useTopNavLinks(): TopNavLink[] {
if (modules?.overview !== false) { if (modules?.overview !== false) {
links.push({ title: t('Overview'), href: '/dashboard' }) links.push({ title: t('Overview'), href: '/dashboard' })
} }
if (modules?.deployments !== false) {
links.push({ title: t('Deployments'), href: '/deployments' })
}
return links return links
} }
-43
View File
@@ -45,13 +45,11 @@ import { Route as AuthenticatedModelsIndexRouteImport } from './routes/_authenti
import { Route as AuthenticatedKeysIndexRouteImport } from './routes/_authenticated/keys/index' import { Route as AuthenticatedKeysIndexRouteImport } from './routes/_authenticated/keys/index'
import { Route as AuthenticatedDevicesIndexRouteImport } from './routes/_authenticated/devices/index' import { Route as AuthenticatedDevicesIndexRouteImport } from './routes/_authenticated/devices/index'
import { Route as AuthenticatedDesktopClientIndexRouteImport } from './routes/_authenticated/desktop-client/index' import { Route as AuthenticatedDesktopClientIndexRouteImport } from './routes/_authenticated/desktop-client/index'
import { Route as AuthenticatedDeploymentsIndexRouteImport } from './routes/_authenticated/deployments/index'
import { Route as AuthenticatedDeployAgentIndexRouteImport } from './routes/_authenticated/deploy-agent/index' import { Route as AuthenticatedDeployAgentIndexRouteImport } from './routes/_authenticated/deploy-agent/index'
import { Route as AuthenticatedDashboardIndexRouteImport } from './routes/_authenticated/dashboard/index' import { Route as AuthenticatedDashboardIndexRouteImport } from './routes/_authenticated/dashboard/index'
import { Route as AuthenticatedChannelsIndexRouteImport } from './routes/_authenticated/channels/index' import { Route as AuthenticatedChannelsIndexRouteImport } from './routes/_authenticated/channels/index'
import { Route as AuthenticatedAvailableModelsIndexRouteImport } from './routes/_authenticated/available-models/index' import { Route as AuthenticatedAvailableModelsIndexRouteImport } from './routes/_authenticated/available-models/index'
import { Route as AuthenticatedUsageLogsSectionRouteImport } from './routes/_authenticated/usage-logs/$section' import { Route as AuthenticatedUsageLogsSectionRouteImport } from './routes/_authenticated/usage-logs/$section'
import { Route as AuthenticatedTasksIdRouteImport } from './routes/_authenticated/tasks/$id'
import { Route as AuthenticatedModelsSectionRouteImport } from './routes/_authenticated/models/$section' import { Route as AuthenticatedModelsSectionRouteImport } from './routes/_authenticated/models/$section'
import { Route as AuthenticatedErrorsErrorRouteImport } from './routes/_authenticated/errors/$error' import { Route as AuthenticatedErrorsErrorRouteImport } from './routes/_authenticated/errors/$error'
import { Route as AuthenticatedDashboardSectionRouteImport } from './routes/_authenticated/dashboard/$section' import { Route as AuthenticatedDashboardSectionRouteImport } from './routes/_authenticated/dashboard/$section'
@@ -262,12 +260,6 @@ const AuthenticatedDesktopClientIndexRoute =
path: '/desktop-client/', path: '/desktop-client/',
getParentRoute: () => AuthenticatedRouteRoute, getParentRoute: () => AuthenticatedRouteRoute,
} as any) } as any)
const AuthenticatedDeploymentsIndexRoute =
AuthenticatedDeploymentsIndexRouteImport.update({
id: '/deployments/',
path: '/deployments/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any)
const AuthenticatedDeployAgentIndexRoute = const AuthenticatedDeployAgentIndexRoute =
AuthenticatedDeployAgentIndexRouteImport.update({ AuthenticatedDeployAgentIndexRouteImport.update({
id: '/deploy-agent/', id: '/deploy-agent/',
@@ -298,11 +290,6 @@ const AuthenticatedUsageLogsSectionRoute =
path: '/usage-logs/$section', path: '/usage-logs/$section',
getParentRoute: () => AuthenticatedRouteRoute, getParentRoute: () => AuthenticatedRouteRoute,
} as any) } as any)
const AuthenticatedTasksIdRoute = AuthenticatedTasksIdRouteImport.update({
id: '/tasks/$id',
path: '/tasks/$id',
getParentRoute: () => AuthenticatedRouteRoute,
} as any)
const AuthenticatedModelsSectionRoute = const AuthenticatedModelsSectionRoute =
AuthenticatedModelsSectionRouteImport.update({ AuthenticatedModelsSectionRouteImport.update({
id: '/models/$section', id: '/models/$section',
@@ -442,13 +429,11 @@ export interface FileRoutesByFullPath {
'/dashboard/$section': typeof AuthenticatedDashboardSectionRoute '/dashboard/$section': typeof AuthenticatedDashboardSectionRoute
'/errors/$error': typeof AuthenticatedErrorsErrorRoute '/errors/$error': typeof AuthenticatedErrorsErrorRoute
'/models/$section': typeof AuthenticatedModelsSectionRoute '/models/$section': typeof AuthenticatedModelsSectionRoute
'/tasks/$id': typeof AuthenticatedTasksIdRoute
'/usage-logs/$section': typeof AuthenticatedUsageLogsSectionRoute '/usage-logs/$section': typeof AuthenticatedUsageLogsSectionRoute
'/available-models/': typeof AuthenticatedAvailableModelsIndexRoute '/available-models/': typeof AuthenticatedAvailableModelsIndexRoute
'/channels/': typeof AuthenticatedChannelsIndexRoute '/channels/': typeof AuthenticatedChannelsIndexRoute
'/dashboard/': typeof AuthenticatedDashboardIndexRoute '/dashboard/': typeof AuthenticatedDashboardIndexRoute
'/deploy-agent/': typeof AuthenticatedDeployAgentIndexRoute '/deploy-agent/': typeof AuthenticatedDeployAgentIndexRoute
'/deployments/': typeof AuthenticatedDeploymentsIndexRoute
'/desktop-client/': typeof AuthenticatedDesktopClientIndexRoute '/desktop-client/': typeof AuthenticatedDesktopClientIndexRoute
'/devices/': typeof AuthenticatedDevicesIndexRoute '/devices/': typeof AuthenticatedDevicesIndexRoute
'/keys/': typeof AuthenticatedKeysIndexRoute '/keys/': typeof AuthenticatedKeysIndexRoute
@@ -503,13 +488,11 @@ export interface FileRoutesByTo {
'/dashboard/$section': typeof AuthenticatedDashboardSectionRoute '/dashboard/$section': typeof AuthenticatedDashboardSectionRoute
'/errors/$error': typeof AuthenticatedErrorsErrorRoute '/errors/$error': typeof AuthenticatedErrorsErrorRoute
'/models/$section': typeof AuthenticatedModelsSectionRoute '/models/$section': typeof AuthenticatedModelsSectionRoute
'/tasks/$id': typeof AuthenticatedTasksIdRoute
'/usage-logs/$section': typeof AuthenticatedUsageLogsSectionRoute '/usage-logs/$section': typeof AuthenticatedUsageLogsSectionRoute
'/available-models': typeof AuthenticatedAvailableModelsIndexRoute '/available-models': typeof AuthenticatedAvailableModelsIndexRoute
'/channels': typeof AuthenticatedChannelsIndexRoute '/channels': typeof AuthenticatedChannelsIndexRoute
'/dashboard': typeof AuthenticatedDashboardIndexRoute '/dashboard': typeof AuthenticatedDashboardIndexRoute
'/deploy-agent': typeof AuthenticatedDeployAgentIndexRoute '/deploy-agent': typeof AuthenticatedDeployAgentIndexRoute
'/deployments': typeof AuthenticatedDeploymentsIndexRoute
'/desktop-client': typeof AuthenticatedDesktopClientIndexRoute '/desktop-client': typeof AuthenticatedDesktopClientIndexRoute
'/devices': typeof AuthenticatedDevicesIndexRoute '/devices': typeof AuthenticatedDevicesIndexRoute
'/keys': typeof AuthenticatedKeysIndexRoute '/keys': typeof AuthenticatedKeysIndexRoute
@@ -568,13 +551,11 @@ export interface FileRoutesById {
'/_authenticated/dashboard/$section': typeof AuthenticatedDashboardSectionRoute '/_authenticated/dashboard/$section': typeof AuthenticatedDashboardSectionRoute
'/_authenticated/errors/$error': typeof AuthenticatedErrorsErrorRoute '/_authenticated/errors/$error': typeof AuthenticatedErrorsErrorRoute
'/_authenticated/models/$section': typeof AuthenticatedModelsSectionRoute '/_authenticated/models/$section': typeof AuthenticatedModelsSectionRoute
'/_authenticated/tasks/$id': typeof AuthenticatedTasksIdRoute
'/_authenticated/usage-logs/$section': typeof AuthenticatedUsageLogsSectionRoute '/_authenticated/usage-logs/$section': typeof AuthenticatedUsageLogsSectionRoute
'/_authenticated/available-models/': typeof AuthenticatedAvailableModelsIndexRoute '/_authenticated/available-models/': typeof AuthenticatedAvailableModelsIndexRoute
'/_authenticated/channels/': typeof AuthenticatedChannelsIndexRoute '/_authenticated/channels/': typeof AuthenticatedChannelsIndexRoute
'/_authenticated/dashboard/': typeof AuthenticatedDashboardIndexRoute '/_authenticated/dashboard/': typeof AuthenticatedDashboardIndexRoute
'/_authenticated/deploy-agent/': typeof AuthenticatedDeployAgentIndexRoute '/_authenticated/deploy-agent/': typeof AuthenticatedDeployAgentIndexRoute
'/_authenticated/deployments/': typeof AuthenticatedDeploymentsIndexRoute
'/_authenticated/desktop-client/': typeof AuthenticatedDesktopClientIndexRoute '/_authenticated/desktop-client/': typeof AuthenticatedDesktopClientIndexRoute
'/_authenticated/devices/': typeof AuthenticatedDevicesIndexRoute '/_authenticated/devices/': typeof AuthenticatedDevicesIndexRoute
'/_authenticated/keys/': typeof AuthenticatedKeysIndexRoute '/_authenticated/keys/': typeof AuthenticatedKeysIndexRoute
@@ -632,13 +613,11 @@ export interface FileRouteTypes {
| '/dashboard/$section' | '/dashboard/$section'
| '/errors/$error' | '/errors/$error'
| '/models/$section' | '/models/$section'
| '/tasks/$id'
| '/usage-logs/$section' | '/usage-logs/$section'
| '/available-models/' | '/available-models/'
| '/channels/' | '/channels/'
| '/dashboard/' | '/dashboard/'
| '/deploy-agent/' | '/deploy-agent/'
| '/deployments/'
| '/desktop-client/' | '/desktop-client/'
| '/devices/' | '/devices/'
| '/keys/' | '/keys/'
@@ -693,13 +672,11 @@ export interface FileRouteTypes {
| '/dashboard/$section' | '/dashboard/$section'
| '/errors/$error' | '/errors/$error'
| '/models/$section' | '/models/$section'
| '/tasks/$id'
| '/usage-logs/$section' | '/usage-logs/$section'
| '/available-models' | '/available-models'
| '/channels' | '/channels'
| '/dashboard' | '/dashboard'
| '/deploy-agent' | '/deploy-agent'
| '/deployments'
| '/desktop-client' | '/desktop-client'
| '/devices' | '/devices'
| '/keys' | '/keys'
@@ -757,13 +734,11 @@ export interface FileRouteTypes {
| '/_authenticated/dashboard/$section' | '/_authenticated/dashboard/$section'
| '/_authenticated/errors/$error' | '/_authenticated/errors/$error'
| '/_authenticated/models/$section' | '/_authenticated/models/$section'
| '/_authenticated/tasks/$id'
| '/_authenticated/usage-logs/$section' | '/_authenticated/usage-logs/$section'
| '/_authenticated/available-models/' | '/_authenticated/available-models/'
| '/_authenticated/channels/' | '/_authenticated/channels/'
| '/_authenticated/dashboard/' | '/_authenticated/dashboard/'
| '/_authenticated/deploy-agent/' | '/_authenticated/deploy-agent/'
| '/_authenticated/deployments/'
| '/_authenticated/desktop-client/' | '/_authenticated/desktop-client/'
| '/_authenticated/devices/' | '/_authenticated/devices/'
| '/_authenticated/keys/' | '/_authenticated/keys/'
@@ -1066,13 +1041,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedDesktopClientIndexRouteImport preLoaderRoute: typeof AuthenticatedDesktopClientIndexRouteImport
parentRoute: typeof AuthenticatedRouteRoute parentRoute: typeof AuthenticatedRouteRoute
} }
'/_authenticated/deployments/': {
id: '/_authenticated/deployments/'
path: '/deployments'
fullPath: '/deployments/'
preLoaderRoute: typeof AuthenticatedDeploymentsIndexRouteImport
parentRoute: typeof AuthenticatedRouteRoute
}
'/_authenticated/deploy-agent/': { '/_authenticated/deploy-agent/': {
id: '/_authenticated/deploy-agent/' id: '/_authenticated/deploy-agent/'
path: '/deploy-agent' path: '/deploy-agent'
@@ -1108,13 +1076,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedUsageLogsSectionRouteImport preLoaderRoute: typeof AuthenticatedUsageLogsSectionRouteImport
parentRoute: typeof AuthenticatedRouteRoute parentRoute: typeof AuthenticatedRouteRoute
} }
'/_authenticated/tasks/$id': {
id: '/_authenticated/tasks/$id'
path: '/tasks/$id'
fullPath: '/tasks/$id'
preLoaderRoute: typeof AuthenticatedTasksIdRouteImport
parentRoute: typeof AuthenticatedRouteRoute
}
'/_authenticated/models/$section': { '/_authenticated/models/$section': {
id: '/_authenticated/models/$section' id: '/_authenticated/models/$section'
path: '/models/$section' path: '/models/$section'
@@ -1339,13 +1300,11 @@ interface AuthenticatedRouteRouteChildren {
AuthenticatedDashboardSectionRoute: typeof AuthenticatedDashboardSectionRoute AuthenticatedDashboardSectionRoute: typeof AuthenticatedDashboardSectionRoute
AuthenticatedErrorsErrorRoute: typeof AuthenticatedErrorsErrorRoute AuthenticatedErrorsErrorRoute: typeof AuthenticatedErrorsErrorRoute
AuthenticatedModelsSectionRoute: typeof AuthenticatedModelsSectionRoute AuthenticatedModelsSectionRoute: typeof AuthenticatedModelsSectionRoute
AuthenticatedTasksIdRoute: typeof AuthenticatedTasksIdRoute
AuthenticatedUsageLogsSectionRoute: typeof AuthenticatedUsageLogsSectionRoute AuthenticatedUsageLogsSectionRoute: typeof AuthenticatedUsageLogsSectionRoute
AuthenticatedAvailableModelsIndexRoute: typeof AuthenticatedAvailableModelsIndexRoute AuthenticatedAvailableModelsIndexRoute: typeof AuthenticatedAvailableModelsIndexRoute
AuthenticatedChannelsIndexRoute: typeof AuthenticatedChannelsIndexRoute AuthenticatedChannelsIndexRoute: typeof AuthenticatedChannelsIndexRoute
AuthenticatedDashboardIndexRoute: typeof AuthenticatedDashboardIndexRoute AuthenticatedDashboardIndexRoute: typeof AuthenticatedDashboardIndexRoute
AuthenticatedDeployAgentIndexRoute: typeof AuthenticatedDeployAgentIndexRoute AuthenticatedDeployAgentIndexRoute: typeof AuthenticatedDeployAgentIndexRoute
AuthenticatedDeploymentsIndexRoute: typeof AuthenticatedDeploymentsIndexRoute
AuthenticatedDesktopClientIndexRoute: typeof AuthenticatedDesktopClientIndexRoute AuthenticatedDesktopClientIndexRoute: typeof AuthenticatedDesktopClientIndexRoute
AuthenticatedDevicesIndexRoute: typeof AuthenticatedDevicesIndexRoute AuthenticatedDevicesIndexRoute: typeof AuthenticatedDevicesIndexRoute
AuthenticatedKeysIndexRoute: typeof AuthenticatedKeysIndexRoute AuthenticatedKeysIndexRoute: typeof AuthenticatedKeysIndexRoute
@@ -1368,14 +1327,12 @@ const AuthenticatedRouteRouteChildren: AuthenticatedRouteRouteChildren = {
AuthenticatedDashboardSectionRoute: AuthenticatedDashboardSectionRoute, AuthenticatedDashboardSectionRoute: AuthenticatedDashboardSectionRoute,
AuthenticatedErrorsErrorRoute: AuthenticatedErrorsErrorRoute, AuthenticatedErrorsErrorRoute: AuthenticatedErrorsErrorRoute,
AuthenticatedModelsSectionRoute: AuthenticatedModelsSectionRoute, AuthenticatedModelsSectionRoute: AuthenticatedModelsSectionRoute,
AuthenticatedTasksIdRoute: AuthenticatedTasksIdRoute,
AuthenticatedUsageLogsSectionRoute: AuthenticatedUsageLogsSectionRoute, AuthenticatedUsageLogsSectionRoute: AuthenticatedUsageLogsSectionRoute,
AuthenticatedAvailableModelsIndexRoute: AuthenticatedAvailableModelsIndexRoute:
AuthenticatedAvailableModelsIndexRoute, AuthenticatedAvailableModelsIndexRoute,
AuthenticatedChannelsIndexRoute: AuthenticatedChannelsIndexRoute, AuthenticatedChannelsIndexRoute: AuthenticatedChannelsIndexRoute,
AuthenticatedDashboardIndexRoute: AuthenticatedDashboardIndexRoute, AuthenticatedDashboardIndexRoute: AuthenticatedDashboardIndexRoute,
AuthenticatedDeployAgentIndexRoute: AuthenticatedDeployAgentIndexRoute, AuthenticatedDeployAgentIndexRoute: AuthenticatedDeployAgentIndexRoute,
AuthenticatedDeploymentsIndexRoute: AuthenticatedDeploymentsIndexRoute,
AuthenticatedDesktopClientIndexRoute: AuthenticatedDesktopClientIndexRoute, AuthenticatedDesktopClientIndexRoute: AuthenticatedDesktopClientIndexRoute,
AuthenticatedDevicesIndexRoute: AuthenticatedDevicesIndexRoute, AuthenticatedDevicesIndexRoute: AuthenticatedDevicesIndexRoute,
AuthenticatedKeysIndexRoute: AuthenticatedKeysIndexRoute, AuthenticatedKeysIndexRoute: AuthenticatedKeysIndexRoute,
@@ -1,6 +0,0 @@
import { createFileRoute } from '@tanstack/react-router'
import { AgentDeploymentsPage } from '@/features/agent-console/pages'
export const Route = createFileRoute('/_authenticated/deployments/')({
component: AgentDeploymentsPage,
})
@@ -1,6 +0,0 @@
import { createFileRoute } from '@tanstack/react-router'
import { TaskCardView } from '@/features/tasks/task-card-view'
export const Route = createFileRoute('/_authenticated/tasks/$id')({
component: TaskCardView,
})