Skip to content

Commit 3de7c13

Browse files
committed
feat: 增 monorepo ai template,支持按名称或任务清单批量生成 Agentic 任务模板
1 parent e5dec44 commit 3de7c13

File tree

16 files changed

+610
-490
lines changed

16 files changed

+610
-490
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@icebreakers/monorepo': minor
3+
---
4+
5+
新增 `monorepo ai template`,支持按名称或任务清单批量生成 Agentic 任务模板,格式/目录/覆盖策略可通过 `monorepo.config.ts` 预设并同步到文档示例。

apps/client/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"vue-router": "^4.6.3"
3030
},
3131
"devDependencies": {
32-
"@cloudflare/vite-plugin": "^1.15.3",
32+
"@cloudflare/vite-plugin": "^1.16.1",
3333
"@hono/node-server": "^1.19.6",
3434
"@hono/trpc-server": "^0.4.0",
3535
"@tailwindcss/vite": "^4.1.17",
@@ -45,7 +45,7 @@
4545
"vite-plugin-vue-devtools": "^8.0.5",
4646
"vite-tsconfig-paths": "^5.1.4",
4747
"vue-tsc": "3.1.5",
48-
"wrangler": "^4.51.0",
48+
"wrangler": "^4.52.1",
4949
"zod": "^4.1.13"
5050
}
5151
}

apps/server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"devDependencies": {
5454
"@hono/node-server": "^1.19.6",
5555
"hono": "^4.10.7",
56-
"wrangler": "^4.51.0",
56+
"wrangler": "^4.52.1",
5757
"zod": "^4.1.13"
5858
}
5959
}

apps/website/index.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,16 @@ npx monorepo clean # 批量删除已勾选的子项目
5353
npx monorepo sync # 同步所有包到 npmmirror
5454
npx monorepo mirror # 写入 VS Code 镜像配置
5555
npx monorepo up # 从最新模板同步配置文件
56+
npx monorepo ai template # 生成 Agentic 任务提示词模板(支持输出到文件)
5657
```
5758

59+
示例:`npx monorepo ai template -o agentic-task.md -f`,可直接生成 Markdown 模板并覆盖旧文件。
60+
61+
多文件场景:
62+
63+
- `npx monorepo ai template --name checkout` 自动落盘到 `agentic/checkout.md`(默认目录可改)。
64+
- `npx monorepo ai template --tasks agentic/tasks.json -f` 读取 JSON 数组批量生成,适合多人协作收口任务。
65+
5866
所有命令都支持在 `monorepo.config.ts` 中覆写默认行为,例如新增模板、修改同步命令、跳过 README 初始化等。配置示例见下文和 [配置中心说明](./monorepo/manage.md#使用-monorepo-configts-定制命令行为)
5967

6068
## 自定义配置:`monorepo.config.ts`
@@ -64,6 +72,13 @@ import { defineMonorepoConfig } from '@icebreakers/monorepo'
6472

6573
export default defineMonorepoConfig({
6674
commands: {
75+
ai: {
76+
output: 'agentic-task.md',
77+
format: 'md',
78+
force: true,
79+
baseDir: 'agentic',
80+
tasksFile: 'agentic/tasks.json',
81+
},
6782
create: {
6883
defaultTemplate: 'cli',
6984
renameJson: true,

apps/website/monorepo/manage.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,15 @@ export default defineMonorepoConfig({
8383

8484
常用配置项:
8585

86-
| 命令 | 可覆盖字段 | 说明 |
87-
| --------- | ---------------------------------------------------------------------------------- | ------------------------------ |
88-
| `create` | `templatesDir` / `templateMap` / `choices` / `defaultTemplate` | 扩展模板来源、修改提示内容 |
89-
| `clean` | `autoConfirm` / `ignorePackages` / `includePrivate` / `pinnedVersion` | 控制交互、过滤包、锁定依赖版本 |
90-
| `sync` | `concurrency` / `command` / `packages` | 定义同步命令与并发度 |
91-
| `upgrade` | `targets` / `mergeTargets` / `scripts` / `skipChangesetMarkdown` / `skipOverwrite` | 改写配置同步策略 |
92-
| `init` | `skipReadme` / `skipPkgJson` / `skipChangeset` | 按需跳过初始化步骤 |
93-
| `mirror` | `env` | 注入镜像环境变量 |
86+
| 命令 | 可覆盖字段 | 说明 |
87+
| --------- | ---------------------------------------------------------------------------------- | ----------------------------------------- |
88+
| `create` | `templatesDir` / `templateMap` / `choices` / `defaultTemplate` | 扩展模板来源、修改提示内容 |
89+
| `clean` | `autoConfirm` / `ignorePackages` / `includePrivate` / `pinnedVersion` | 控制交互、过滤包、锁定依赖版本 |
90+
| `sync` | `concurrency` / `command` / `packages` | 定义同步命令与并发度 |
91+
| `upgrade` | `targets` / `mergeTargets` / `scripts` / `skipChangesetMarkdown` / `skipOverwrite` | 改写配置同步策略 |
92+
| `init` | `skipReadme` / `skipPkgJson` / `skipChangeset` | 按需跳过初始化步骤 |
93+
| `mirror` | `env` | 注入镜像环境变量 |
94+
| `ai` | `output` / `format` / `force` / `baseDir` / `tasksFile` | 预设 Agentic 模板输出目录、格式与批量任务 |
9495

9596
更多细节可参考 CLI 命令文档或源码中的 `commands/*`
9697

monorepo.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
import { randomUUID } from 'node:crypto'
12
import { defineMonorepoConfig } from '@icebreakers/monorepo'
23

4+
const randomPromptOutput = () => `agentic/prompts/prompt-${randomUUID()}.md`
5+
36
export default defineMonorepoConfig({
47
commands: {
8+
ai: {
9+
output: randomPromptOutput(),
10+
baseDir: 'agentic/prompts',
11+
format: 'md',
12+
force: true,
13+
},
514
create: {
615
defaultTemplate: 'unbuild',
716
renameJson: false,

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@
6565
"pkg-types": "^2.3.0",
6666
"rimraf": "^6.1.2",
6767
"stylelint": "^16.26.1",
68-
"tsdown": "^0.16.8",
68+
"tsdown": "0.17.0-beta.6",
6969
"tslib": "^2.8.1",
7070
"tsup": "^8.5.1",
7171
"tsx": "^4.21.0",
72-
"turbo": "^2.6.1",
72+
"turbo": "^2.6.2",
7373
"type-fest": "^5.3.0",
7474
"typescript": "^5.9.3",
7575
"unbuild": "^3.6.1",

packages/monorepo/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ pnpm add -D @icebreakers/monorepo@latest
1111
npx monorepo up
1212
# 帮助文档
1313
npx monorepo -h
14+
# 生成 Agentic 任务模板
15+
npx monorepo ai template -o agentic-task.md -f
16+
```
17+
18+
`monorepo ai template` 支持批量生成:
19+
20+
```bash
21+
# 基于名称自动落盘到 agentic/checkout.md(默认目录可在 monorepo.config.ts 中设置)
22+
npx monorepo ai template --name checkout
23+
24+
# 使用任务清单一次生成多个文件(tasks.json 为字符串或对象数组)
25+
npx monorepo ai template --tasks agentic/tasks.json --format md -f
26+
```
27+
28+
`agentic/tasks.json` 示例:
29+
30+
```json
31+
[
32+
"checkout",
33+
{ "name": "payments", "format": "json", "force": true }
34+
]
1435
```
1536

1637
### 配置文件
@@ -23,6 +44,13 @@ import { defineMonorepoConfig } from '@icebreakers/monorepo'
2344

2445
export default defineMonorepoConfig({
2546
commands: {
47+
ai: {
48+
output: 'agentic-task.md',
49+
format: 'md',
50+
force: true,
51+
baseDir: 'agentic',
52+
tasksFile: 'agentic/tasks.json',
53+
},
2654
create: {
2755
defaultTemplate: 'cli',
2856
renameJson: true,

packages/monorepo/src/cli/program.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1+
import type { AgenticTemplateFormat } from '../commands'
12
import type { CreateNewProjectOptions } from '../commands/create'
23
import type { CliOpts } from '../types'
34
import process from 'node:process'
45
import input from '@inquirer/input'
56
import select from '@inquirer/select'
67
import { program } from 'commander'
7-
import { cleanProjects, createNewProject, getCreateChoices, init, setVscodeBinaryMirror, syncNpmMirror, upgradeMonorepo } from '../commands'
8+
import { cleanProjects, createNewProject, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, init, loadAgenticTasks, setVscodeBinaryMirror, syncNpmMirror, upgradeMonorepo } from '../commands'
89
import { defaultTemplate } from '../commands/create'
910
import { name, version } from '../constants'
1011
import { resolveCommandConfig } from '../core/config'
1112
import { logger } from '../core/logger'
1213

14+
interface AiTemplateCommandOptions {
15+
output?: string
16+
force?: boolean
17+
format?: AgenticTemplateFormat
18+
dir?: string
19+
name?: string
20+
tasks?: string
21+
}
22+
1323
const cwd = process.cwd()
1424

1525
program.name(name).version(version)
@@ -55,6 +65,48 @@ program.command('mirror').description('设置 VscodeBinaryMirror').action(async
5565
logger.success('set vscode binary mirror finished!')
5666
})
5767

68+
const aiCommand = program.command('ai').description('AI 助手工具集')
69+
70+
aiCommand.command('template')
71+
.description('生成 Agentic 任务提示词模板')
72+
.option('-o, --output <path>', '输出到指定文件')
73+
.option('-f, --force', '允许覆盖已存在文件')
74+
.option('--format <md|json>', '模板格式,默认 md', 'md')
75+
.option('-d, --dir <path>', '默认输出目录,配合 --name / --tasks 使用', 'agentic')
76+
.option('-n, --name <name>', '使用名称快速生成文件,自动添加后缀')
77+
.option('-t, --tasks <file>', '从 JSON 数组批量生成模板')
78+
.action(async (opts: AiTemplateCommandOptions) => {
79+
const aiConfig = await resolveCommandConfig('ai', cwd)
80+
const format = opts.format ?? aiConfig?.format ?? 'md'
81+
const force = opts.force ?? aiConfig?.force ?? false
82+
const output = opts.output ?? aiConfig?.output
83+
const baseDir = opts.dir ?? aiConfig?.baseDir ?? 'agentic'
84+
const tasksFile = opts.tasks ?? aiConfig?.tasksFile
85+
const name = opts.name
86+
87+
const shouldUseTasks = Boolean(tasksFile && !opts.output && !opts.name)
88+
89+
if (shouldUseTasks) {
90+
const tasks = await loadAgenticTasks(tasksFile, cwd)
91+
await generateAgenticTemplates(tasks, {
92+
cwd,
93+
baseDir,
94+
force,
95+
format,
96+
})
97+
return
98+
}
99+
100+
await generateAgenticTemplate({
101+
cwd,
102+
output,
103+
force,
104+
format,
105+
baseDir,
106+
name,
107+
})
108+
})
109+
58110
program.command('new')
59111
.description('创建一个新的子包')
60112
.alias('create')
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import process from 'node:process'
2+
import fs from 'fs-extra'
3+
import path from 'pathe'
4+
import { logger } from '../core/logger'
5+
6+
export type AgenticTemplateFormat = 'md' | 'json'
7+
8+
export interface GenerateAgenticTemplateOptions {
9+
cwd?: string
10+
output?: string
11+
force?: boolean
12+
format?: AgenticTemplateFormat
13+
/**
14+
* 任务名,用于快速生成带目录与后缀的文件。
15+
*/
16+
name?: string
17+
/**
18+
* 基础目录,配合 name 使用。
19+
* @default 'agentic'
20+
*/
21+
baseDir?: string
22+
}
23+
24+
export type AgenticTemplateTask = string | (Omit<GenerateAgenticTemplateOptions, 'cwd'> & { name?: string })
25+
26+
const agenticSections = [
27+
'目标/产物',
28+
'约束(性能/风格/兼容/不可改动范围)',
29+
'验收标准(要跑的命令、预期输出/文件)',
30+
'仓库路径',
31+
'允许操作(可/不可写文件,可运行的命令清单,可否联网)',
32+
'上下文线索(日志/文件/模块/相关 issue)',
33+
'里程碑(根因→设计→实现→验证)',
34+
] as const
35+
36+
function renderMarkdownTemplate() {
37+
return `${agenticSections.map(title => `## ${title}\n- `).join('\n\n')}\n`
38+
}
39+
40+
function renderJsonTemplate() {
41+
const payload: Record<string, string> = {}
42+
for (const title of agenticSections) {
43+
payload[title] = ''
44+
}
45+
return `${JSON.stringify(payload, null, 2)}\n`
46+
}
47+
48+
/**
49+
* 生成 Agentic 任务提示词模板,支持输出到 stdout 或文件。
50+
*/
51+
export async function generateAgenticTemplate(options: GenerateAgenticTemplateOptions = {}) {
52+
const cwd = options.cwd ?? process.cwd()
53+
const format = options.format ?? 'md'
54+
const baseDir = options.baseDir ?? 'agentic'
55+
56+
if (format !== 'md' && format !== 'json') {
57+
throw new Error(`不支持的模板格式:${format}`)
58+
}
59+
60+
const template = format === 'md'
61+
? renderMarkdownTemplate()
62+
: renderJsonTemplate()
63+
64+
const ext = format === 'json' ? 'json' : 'md'
65+
let outputPath = options.output
66+
if (!outputPath && options.name) {
67+
outputPath = path.join(baseDir, `${options.name}.${ext}`)
68+
}
69+
70+
if (!outputPath) {
71+
process.stdout.write(template)
72+
return template
73+
}
74+
75+
const targetPath = path.resolve(cwd, outputPath)
76+
const targetDir = path.dirname(targetPath)
77+
await fs.ensureDir(targetDir)
78+
const exists = await fs.pathExists(targetPath)
79+
80+
if (exists && !options.force) {
81+
throw new Error(`目标文件已存在:${path.relative(cwd, targetPath)}`)
82+
}
83+
84+
await fs.outputFile(targetPath, template, 'utf8')
85+
const actionLabel = exists ? '已覆盖模板' : '已生成模板'
86+
logger.success(`${actionLabel}${path.relative(cwd, targetPath)}`)
87+
88+
return template
89+
}
90+
91+
export async function loadAgenticTasks(filePath: string, cwd: string) {
92+
const fullPath = path.resolve(cwd, filePath)
93+
const tasks = await fs.readJson(fullPath)
94+
if (!Array.isArray(tasks)) {
95+
throw new TypeError('任务清单需要是数组')
96+
}
97+
return tasks as AgenticTemplateTask[]
98+
}
99+
100+
export async function generateAgenticTemplates(tasks: AgenticTemplateTask[], defaults: GenerateAgenticTemplateOptions = {}) {
101+
const results: string[] = []
102+
for (const task of tasks) {
103+
const normalized = typeof task === 'string'
104+
? { ...defaults, name: task }
105+
: { ...defaults, ...task }
106+
results.push(await generateAgenticTemplate(normalized))
107+
}
108+
return results
109+
}

0 commit comments

Comments
 (0)