Files
claude-code/src/utils/autonomyStatus.ts
claude-code-best 1ac18aec0d chore: 清理 4 处遗漏的未使用导入和参数
移除 autonomyStatus/betas/claudemd/executorCrossPlatform 中
未使用的导入和参数。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 20:05:50 +08:00

222 lines
6.4 KiB
TypeScript

import { readdir } from 'fs/promises'
import { queryDaemonStatus } from '../daemon/state.js'
import { listLiveSessions } from '../cli/bg.js'
import {
type AutonomyFlowRecord,
formatAutonomyFlowsStatus,
} from './autonomyFlows.js'
import {
type AutonomyRunRecord,
formatAutonomyRunsStatus,
} from './autonomyRuns.js'
import { getTeamsDir } from './envUtils.js'
import {
isAutoModeGateEnabled,
getAutoModeUnavailableReason,
} from './permissions/permissionSetup.js'
import { cronToHuman } from './cron.js'
import { listAllCronTasks, nextCronRunMs } from './cronTasks.js'
import { getTeammateStatuses } from './teamDiscovery.js'
import { listTasks } from './tasks.js'
import {
formatRemoteTriggerAuditStatus,
listRemoteTriggerAuditRecords,
} from './remoteTriggerAudit.js'
import { formatWorkflowRunsStatus, listWorkflowRuns } from './workflowRuns.js'
import { formatPipeRegistryStatus } from './pipeStatus.js'
import { formatRemoteControlLocalStatus } from './remoteControlStatus.js'
type DeepStatusParams = {
runs: AutonomyRunRecord[]
flows: AutonomyFlowRecord[]
nowMs?: number
}
export type AutonomyDeepStatusSectionId =
| 'auto-mode'
| 'runs'
| 'flows'
| 'cron'
| 'workflow-runs'
| 'teams'
| 'pipes'
| 'runtime'
| 'remote-control'
| 'remote-trigger'
export type AutonomyDeepStatusSection = {
id: AutonomyDeepStatusSectionId
title: string
content: string
}
async function listTeamNames(): Promise<string[]> {
try {
const entries = await readdir(getTeamsDir(), { withFileTypes: true })
return entries
.filter(e => e.isDirectory())
.map(e => e.name)
.sort()
} catch {
return []
}
}
async function formatTeamsSection(): Promise<string> {
const teamNames = await listTeamNames()
if (teamNames.length === 0) {
return ['Teams: 0', ' none'].join('\n')
}
const lines = [`Teams: ${teamNames.length}`]
for (const teamName of teamNames) {
const teammates = getTeammateStatuses(teamName)
const tasks = await listTasks(teamName)
const openTasks = tasks.filter(t => t.status !== 'completed')
const running = teammates.filter(t => t.status === 'running').length
const idle = teammates.filter(t => t.status === 'idle').length
lines.push(
` ${teamName}: teammates=${teammates.length} running=${running} idle=${idle} open_tasks=${openTasks.length}`,
)
for (const teammate of teammates.slice(0, 5)) {
const ownerTasks = openTasks.filter(
t => t.owner === teammate.name || t.owner === teammate.agentId,
)
lines.push(
` @${teammate.name}: ${teammate.status} backend=${teammate.backendType ?? 'unknown'} mode=${teammate.mode ?? 'default'} tasks=${ownerTasks.length}`,
)
}
if (teammates.length > 5) {
lines.push(` ... ${teammates.length - 5} more teammate(s)`)
}
}
return lines.join('\n')
}
async function formatCronSection(nowMs: number): Promise<string> {
const jobs = await listAllCronTasks()
if (jobs.length === 0) {
return ['Cron jobs: 0', ' none'].join('\n')
}
const lines = [`Cron jobs: ${jobs.length}`]
for (const job of jobs.slice(0, 10)) {
const next = nextCronRunMs(job.cron, nowMs)
lines.push(
` ${job.id}: ${cronToHuman(job.cron)} ${job.recurring ? 'recurring' : 'one-shot'} ${job.durable === false ? 'session-only' : 'durable'} next=${next ? new Date(next).toLocaleString() : 'none'}`,
)
}
if (jobs.length > 10) {
lines.push(` ... ${jobs.length - 10} more job(s)`)
}
return lines.join('\n')
}
async function formatRuntimeSection(): Promise<string> {
const daemon = queryDaemonStatus()
const sessions = await listLiveSessions()
const lines = [
`Daemon: ${daemon.status}${daemon.state ? ` pid=${daemon.state.pid} workers=${daemon.state.workerKinds.join(',')}` : ''}`,
`Background sessions: ${sessions.length}`,
]
for (const session of sessions.slice(0, 8)) {
lines.push(
` pid=${session.pid} kind=${session.kind} status=${session.status ?? 'unknown'} cwd=${session.cwd}`,
)
}
if (sessions.length > 8) {
lines.push(` ... ${sessions.length - 8} more session(s)`)
}
return lines.join('\n')
}
function formatAutoModeSection(): string {
let available = false
let reason: string | null = null
try {
available = isAutoModeGateEnabled()
reason = getAutoModeUnavailableReason()
} catch (error) {
return [
'Auto mode: unknown',
` reason=${error instanceof Error ? error.message : String(error)}`,
].join('\n')
}
return [
`Auto mode: ${available ? 'available' : 'unavailable'}`,
` reason=${reason ?? 'none'}`,
].join('\n')
}
export async function formatAutonomyDeepStatusSections({
runs,
flows,
nowMs = Date.now(),
}: DeepStatusParams): Promise<AutonomyDeepStatusSection[]> {
return Promise.all([
Promise.resolve({
id: 'auto-mode' as const,
title: 'Auto Mode',
content: formatAutoModeSection(),
}),
Promise.resolve({
id: 'runs' as const,
title: 'Runs',
content: formatAutonomyRunsStatus(runs),
}),
Promise.resolve({
id: 'flows' as const,
title: 'Flows',
content: formatAutonomyFlowsStatus(flows),
}),
formatCronSection(nowMs).then(content => ({
id: 'cron' as const,
title: 'Cron',
content,
})),
listWorkflowRuns().then(runs => ({
id: 'workflow-runs' as const,
title: 'Workflow Runs',
content: formatWorkflowRunsStatus(runs),
})),
formatTeamsSection().then(content => ({
id: 'teams' as const,
title: 'Teams',
content,
})),
formatPipeRegistryStatus().then(content => ({
id: 'pipes' as const,
title: 'Pipes',
content,
})),
formatRuntimeSection().then(content => ({
id: 'runtime' as const,
title: 'Runtime',
content,
})),
Promise.resolve({
id: 'remote-control' as const,
title: 'Remote Control',
content: formatRemoteControlLocalStatus(),
}),
listRemoteTriggerAuditRecords().then(records => ({
id: 'remote-trigger' as const,
title: 'RemoteTrigger',
content: formatRemoteTriggerAuditStatus(records),
})),
])
}
export async function formatAutonomyDeepStatus(
params: DeepStatusParams,
): Promise<string> {
const sections = await formatAutonomyDeepStatusSections(params)
return sections
.map((section, index) =>
[
index === 0 ? '# Autonomy Deep Status' : `## ${section.title}`,
section.content,
].join('\n'),
)
.join('\n\n')
}