@ultime/codecraft 1.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,100 @@
1
+ import fs from 'node:fs'
2
+ import os from 'node:os'
3
+ import path from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+
6
+ const PACKAGE_ROOT = fileURLToPath(new URL('..', import.meta.url))
7
+ const SKILL_FILES = ['SKILL.md']
8
+ const SKILL_DIRS = ['docs', 'scenarios', 'prompts']
9
+
10
+ const AGENT_DIRS = {
11
+ claude: '.claude/skills',
12
+ trae: '.trae/skills',
13
+ cursor: '.cursor/skills',
14
+ generic: '.agents/skills',
15
+ }
16
+
17
+ const AGENT_MARKERS = {
18
+ claude: ['.claude', 'CLAUDE.md'],
19
+ trae: ['.trae'],
20
+ cursor: ['.cursor'],
21
+ generic: ['.agents'],
22
+ }
23
+
24
+ export const AGENTS = Object.keys(AGENT_DIRS)
25
+
26
+ export function parseAgents(value) {
27
+ if (!value || value === 'auto') return []
28
+ const agents = [...new Set(value.split(',').map((item) => item.trim()).filter(Boolean))]
29
+ const invalid = agents.filter((agent) => !AGENTS.includes(agent))
30
+ if (invalid.length) {
31
+ throw new Error(`unknown agent: ${invalid.join(', ')}(可选:auto, ${AGENTS.join(', ')})`)
32
+ }
33
+ return agents
34
+ }
35
+
36
+ export function buildInstallPlan(root, options = {}) {
37
+ const base = options.global ? os.homedir() : path.resolve(root)
38
+ const explicit = options.agents ?? []
39
+ const invalid = explicit.filter((agent) => !AGENTS.includes(agent))
40
+ if (invalid.length) {
41
+ throw new Error(`unknown agent: ${invalid.join(', ')}(可选:${AGENTS.join(', ')})`)
42
+ }
43
+
44
+ const agents = explicit.length ? explicit : detectAgents(base, options.global)
45
+ const destinations = options.dest
46
+ ? [{ agent: 'custom', dir: path.resolve(base, options.dest) }]
47
+ : agents.map((agent) => ({ agent, dir: path.join(base, AGENT_DIRS[agent]) }))
48
+
49
+ assertSource()
50
+
51
+ return destinations.map(({ agent, dir }) => {
52
+ const target = path.join(dir, 'codecraft')
53
+ const exists = fs.existsSync(target)
54
+ return { agent, target, exists, action: exists ? 'exists' : 'create' }
55
+ })
56
+ }
57
+
58
+ export function applyInstallPlan(plan, options = {}) {
59
+ const created = []
60
+ const skipped = []
61
+ const replaced = []
62
+
63
+ for (const entry of plan) {
64
+ if (entry.exists && !options.force) {
65
+ skipped.push(entry.target)
66
+ continue
67
+ }
68
+ if (entry.exists) {
69
+ fs.rmSync(entry.target, { recursive: true, force: true })
70
+ replaced.push(entry.target)
71
+ }
72
+
73
+ fs.mkdirSync(entry.target, { recursive: true })
74
+ for (const file of SKILL_FILES) {
75
+ fs.copyFileSync(path.join(PACKAGE_ROOT, file), path.join(entry.target, file))
76
+ }
77
+ for (const dir of SKILL_DIRS) {
78
+ fs.cpSync(path.join(PACKAGE_ROOT, dir), path.join(entry.target, dir), { recursive: true })
79
+ }
80
+ created.push(entry.target)
81
+ }
82
+
83
+ return { created, skipped, replaced }
84
+ }
85
+
86
+ function detectAgents(base, global) {
87
+ const found = AGENTS.filter((agent) =>
88
+ AGENT_MARKERS[agent].some((marker) => fs.existsSync(path.join(base, marker))),
89
+ )
90
+ if (global) return found.length ? found : ['generic']
91
+ return [...new Set([...found, 'generic'])]
92
+ }
93
+
94
+ function assertSource() {
95
+ for (const file of SKILL_FILES) {
96
+ if (!fs.existsSync(path.join(PACKAGE_ROOT, file))) {
97
+ throw new Error(`skill source is incomplete: missing ${file}`)
98
+ }
99
+ }
100
+ }
@@ -8,7 +8,7 @@
8
8
  |---|---|
9
9
  | `src/pages` | 页面:一个页面一个编排入口,只编排 |
10
10
  | `src/components` | 展示与交互组件;原语薄、业务组件按域 |
11
- | `src/behavior` | 页面无关行为(hooks / composables) |
11
+ | `src/behavior` | 页面无关行为:默认纯 TS core,框架绑定作薄适配(hooks / composables) |
12
12
  | `src/api` | 请求收口;唯一可接触 `external/` 的层 |
13
13
  | `src/adapters` | 平台适配(请求 / 存储 / 路由 / 导出) |
14
14
  | `src/types` | 内部类型:通用层与业务层 |
@@ -17,6 +17,7 @@
17
17
  ## 规则
18
18
 
19
19
  - `pages / components / behavior` 不 import `external/` 或 `generated/`。
20
+ - 原生能表达的先写原生;Vue / React 只作页面与组件的落点。
20
21
  - 外部类型只在 `api` / `adapters` 内转成内部类型。
21
22
  - 鉴权失效、错误提示、分页各一处收口。
22
23
  - 状态用联合类型;非法状态不可表示。