mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 14:25:51 +00:00
Squashed merge of: 1. fix/mcp-tsc-errors — 修复上游 MCP 重构后的 tsc 错误和测试失败 2. feat/pipe-mute-disconnect — Pipe IPC 逻辑断开、/lang 命令、mute 状态机 3. feat/stub-recovery-all — 实现全部 stub 恢复 (task 001-012) 4. feat/kairos-activation — KAIROS 激活解除阻塞 + 工具实现 5. codex/openclaw-autonomy-pr — 自治权限系统、运行记录、managed flows Additional: 6. daemon/job 命令层级化重构 (subcommand 架构) 7. 跨平台后台引擎抽象 (detached/tmux engines) 8. 修复 src/ 中 43 个预存在的 TypeScript 类型错误 9. 修复 langfuse isolated test mock 完整性 10. 修复 CodeRabbit 审查的 Critical/Major/Minor 问题 11. remote-control-server logger 抽象 (测试 stderr 静默化) 12. /simplify 审查修复 (代码复用、质量、效率)
159 lines
3.8 KiB
TypeScript
159 lines
3.8 KiB
TypeScript
import { randomUUID } from 'crypto'
|
|
import { listTemplates, loadTemplate } from '../../jobs/templates.js'
|
|
import {
|
|
createJob,
|
|
readJobState,
|
|
appendJobReply,
|
|
getJobDir,
|
|
} from '../../jobs/state.js'
|
|
|
|
/**
|
|
* Entry point for template job commands: `new`, `list`, `reply`.
|
|
* Called from cli.tsx fast-path.
|
|
*/
|
|
export async function templatesMain(args: string[]): Promise<void> {
|
|
const subcommand = args[0]
|
|
|
|
switch (subcommand) {
|
|
case 'list':
|
|
handleList()
|
|
break
|
|
case 'new':
|
|
handleNew(args.slice(1))
|
|
break
|
|
case 'reply':
|
|
handleReply(args.slice(1))
|
|
break
|
|
case 'status':
|
|
handleStatus(args.slice(1))
|
|
break
|
|
default:
|
|
console.error(`Unknown template command: ${subcommand}`)
|
|
printUsage()
|
|
process.exitCode = 1
|
|
}
|
|
}
|
|
|
|
function printUsage(): void {
|
|
console.log(`
|
|
Template Job Commands:
|
|
|
|
claude job list List available templates
|
|
claude job new <template> [args] Create a new job from a template
|
|
claude job reply <job-id> <text> Reply to an existing job
|
|
claude job status <job-id> Show job status
|
|
`)
|
|
}
|
|
|
|
function handleStatus(args: string[]): void {
|
|
const jobId = args[0]
|
|
if (!jobId) {
|
|
console.error('Usage: claude job status <job-id>')
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
const state = readJobState(jobId)
|
|
if (!state) {
|
|
console.error(`Job not found: ${jobId}`)
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
console.log(`Job: ${state.jobId}`)
|
|
console.log(` Template: ${state.templateName}`)
|
|
console.log(` Status: ${state.status}`)
|
|
console.log(` Created: ${state.createdAt}`)
|
|
console.log(` Updated: ${state.updatedAt}`)
|
|
console.log(` Args: ${state.args.join(' ') || '(none)'}`)
|
|
}
|
|
|
|
function handleList(): void {
|
|
const templates = listTemplates()
|
|
|
|
if (templates.length === 0) {
|
|
console.log('No templates found.')
|
|
console.log('Place .md files in .claude/templates/ or ~/.claude/templates/')
|
|
return
|
|
}
|
|
|
|
console.log(
|
|
`${templates.length} template${templates.length > 1 ? 's' : ''} found:\n`,
|
|
)
|
|
|
|
for (const t of templates) {
|
|
console.log(` ${t.name}`)
|
|
console.log(` ${t.description}`)
|
|
console.log(` Path: ${t.filePath}`)
|
|
console.log()
|
|
}
|
|
}
|
|
|
|
function handleNew(args: string[]): void {
|
|
const templateName = args[0]
|
|
if (!templateName) {
|
|
console.error('Usage: claude job new <template> [args...]')
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
const template = loadTemplate(templateName)
|
|
if (!template) {
|
|
console.error(`Template not found: ${templateName}`)
|
|
console.log('\nAvailable templates:')
|
|
for (const t of listTemplates()) {
|
|
console.log(` ${t.name}`)
|
|
}
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
const jobId = randomUUID().slice(0, 8)
|
|
const inputText = args.slice(1).join(' ')
|
|
const rawContent = `---\n${Object.entries(template.frontmatter)
|
|
.map(([k, v]) => `${k}: ${v}`)
|
|
.join('\n')}\n---\n${template.content}`
|
|
|
|
const dir = createJob(
|
|
jobId,
|
|
templateName,
|
|
rawContent,
|
|
inputText,
|
|
args.slice(1),
|
|
)
|
|
|
|
console.log(`Job created: ${jobId}`)
|
|
console.log(` Template: ${templateName}`)
|
|
console.log(` Directory: ${dir}`)
|
|
if (inputText) {
|
|
console.log(` Input: ${inputText}`)
|
|
}
|
|
}
|
|
|
|
function handleReply(args: string[]): void {
|
|
const jobId = args[0]
|
|
const text = args.slice(1).join(' ')
|
|
|
|
if (!jobId || !text) {
|
|
console.error('Usage: claude job reply <job-id> <text>')
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
const state = readJobState(jobId)
|
|
if (!state) {
|
|
console.error(`Job not found: ${jobId}`)
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
const ok = appendJobReply(jobId, text)
|
|
if (ok) {
|
|
console.log(`Reply added to job ${jobId}`)
|
|
console.log(` Directory: ${getJobDir(jobId)}`)
|
|
} else {
|
|
console.error(`Failed to append reply to job ${jobId}`)
|
|
process.exitCode = 1
|
|
}
|
|
}
|