@migor/cli 0.2.1 → 0.3.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.
package/dist/templates.js CHANGED
@@ -14,16 +14,31 @@ export function kebabToPascal(name) {
14
14
  export function kebabToSnake(name) {
15
15
  return name.replace(/-/g, '_');
16
16
  }
17
- export const UNIT_TYPES = ['tool', 'skill', 'prompt', 'subagent'];
18
- export function isUnitType(value) {
19
- return UNIT_TYPES.includes(value);
17
+ export const CAPABILITY_TYPES = ['tool', 'skill', 'prompt', 'subagent'];
18
+ export function isCapabilityType(value) {
19
+ return CAPABILITY_TYPES.includes(value);
20
20
  }
21
- // ---------- units.ts 注册表模板 ----------
21
+ // ---------- 目录约定(spec §7:四分类目录,一能力一文件夹,无伞形词) ----------
22
+ /**
23
+ * 能力类型 → 分类目录。目录名即「里面装什么」,不再用一个需要图例解释的伞形词:
24
+ * 用户看一眼 `src/tools/weather/index.ts` 就知道它是工具。
25
+ */
26
+ export const CAPABILITY_DIRS = {
27
+ tool: 'src/tools',
28
+ skill: 'src/skills',
29
+ prompt: 'src/prompts',
30
+ subagent: 'src/subagents',
31
+ };
32
+ /** 全部能力目录(顺序即 discover 的装配顺序) */
33
+ export const CAPABILITY_DIR_LIST = CAPABILITY_TYPES.map((t) => CAPABILITY_DIRS[t]);
34
+ /** 显式注册表位置(`agentia g` / `agentia add` 维护,`agentia doctor` 校验) */
35
+ export const REGISTRY_PATH = 'src/registry.ts';
36
+ // ---------- 注册表模板 ----------
22
37
  export const IMPORTS_END_MARKER = '// @agentia:imports-end';
23
38
  export const ENTRIES_END_MARKER = '// @agentia:entries-end';
24
- /** 空注册表模板(无任何单元条目) */
39
+ /** 空注册表模板(无任何能力条目) */
25
40
  export function emptyRegistryTemplate() {
26
- return `// Agentia 单元注册表 —— 由 agentia CLI 维护(agentia g 自动更新,也可手工编辑)
41
+ return `// Agentia 能力注册表 —— 由 agentia CLI 维护(agentia g 自动更新,也可手工编辑)
27
42
  // @agentia:imports
28
43
  ${IMPORTS_END_MARKER}
29
44
  import type { Provider } from '@migor/agentia';
@@ -45,7 +60,7 @@ export function projectPackageJson(name) {
45
60
  dev: 'tsx src/main.ts',
46
61
  typecheck: 'tsc --noEmit -p tsconfig.json',
47
62
  },
48
- dependencies: { '@migor/agentia': '^0.2.0' },
63
+ dependencies: { '@migor/agentia': '^0.3.0' },
49
64
  devDependencies: {
50
65
  tsx: '^4.19.0',
51
66
  typescript: '^7.0.2',
@@ -64,78 +79,129 @@ export function projectTsconfig() {
64
79
  esModuleInterop: true,
65
80
  skipLibCheck: true,
66
81
  },
67
- include: ['src', 'units.ts'],
82
+ include: ['src'],
68
83
  }, null, 2)}\n`;
69
84
  }
70
85
  export function mainTs(name) {
71
- return `import { createApp, SystemPrompt } from '@migor/agentia';
86
+ return `import { createApp, loadEnvFile, SystemPrompt } from '@migor/agentia';
87
+
88
+ // 读同目录的 .env(key 写文件里即可,不必每次 export)。框架**不自动**读 .env ——
89
+ // 读哪个文件、什么时候读由这里决定;已存在的真实环境变量优先,不会被文件覆盖。
90
+ // 想换路径/顺序:loadEnvFile({ path: '.env.local' }) 或直接删掉这一行改用自己的加载器。
91
+ loadEnvFile();
72
92
 
73
93
  const app = await createApp({
74
94
  name: '${name}',
75
- discover: 'units', // 目录约定:units/<name>/ 一单元一文件夹,启动期扫描装配
76
- system: new SystemPrompt().add('role', '你是 ${name} 的主 agent,按任务自主调度菜单里的单元。', true),
95
+ discover: [${CAPABILITY_DIR_LIST.map((p) => `'${p}'`).join(', ')}], // 四分类目录,顺序即装配顺序
96
+ system: new SystemPrompt().add('role', '你是 ${name} 的主 agent,按任务自主调度菜单里的能力。', true),
77
97
  });
78
98
 
79
99
  const { result } = await app.run(
80
100
  [{ role: 'user', content: process.argv[2] ?? '介绍一下你自己' }],
81
101
  );
82
- console.log(result.finalText);
102
+
103
+ // 注意:run 失败**不会抛**(硬失败被记进 result.error 与 trace 后正常返回)—— 不显式检查就会
104
+ // 「打印一行空白 + 退出 0」,让首次运行(比如忘了配 ANTHROPIC_API_KEY)看起来像成功。
105
+ if (result.error) {
106
+ console.error(\`run 失败(stopReason=\${result.stopReason}):\${result.error.message}\`);
107
+ console.error('提示:模型调用读 ANTHROPIC_API_KEY —— 填进 .env(首行 loadEnvFile() 会读)或 export 均可;');
108
+ console.error(' 换端点 / 注入自定义 client 见项目内 AGENTS.md。');
109
+ process.exitCode = 1;
110
+ }
111
+ if (result.finalText) console.log(result.finalText);
83
112
  `;
84
113
  }
85
114
  export function projectReadme(name) {
86
115
  return `# ${name}
87
116
 
88
- 基于 [Agentia](https://github.com/) 框架的 agent 应用。
117
+ 基于 [Agentia](https://github.com/retrychx/agentia) 框架的 agent 应用。
89
118
 
90
119
  ## 目录约定
91
120
 
92
- \`units/<name>/\` 一单元一文件夹,每个单元是一个 default export 的类,用装饰器声明能力:
121
+ 四分类目录,一能力一文件夹,每个能力是一个 default export 的类,用装饰器声明:
93
122
 
94
- - \`@Tool\` 工具:主 agent 可调用(input → value)
95
- - \`@Skill\` 技能:方法体内通过 \`ctx.llm()\` 调 LLM
96
- - \`@SubAgent\` 子代理:按 system 角色设定独立跑一轮
97
- - \`@Prompt\` 文本资产:.md 文件,按需拉取进上下文
123
+ - \`src/tools/<name>/\` —— \`@Tool\` 工具:主 agent 可调用(input → value)
124
+ - \`src/skills/<name>/\` —— \`@Skill\` 技能:方法体内通过 \`ctx.llm()\` 调 LLM
125
+ - \`src/subagents/<name>/\` —— \`@SubAgent\` 子代理:按 system 角色设定独立跑一轮
126
+ - \`src/prompts/<name>/\` —— \`@Prompt\` 文本资产:.md 文件,按需拉取进上下文
127
+
128
+ 目录名就是类型,不用记别名。
98
129
 
99
130
  ## 两条装配路线
100
131
 
101
- 1. **目录扫描**:\`createApp({ discover: 'units' })\` 启动期扫描 \`units/*/index.ts\`,default export 为类时以文件夹名为 DI token 注册(见 \`src/main.ts\`)。
102
- 2. **显式装配**:\`createApp({ providers, system })\`,providers 来自 \`units.ts\` 注册表(由 \`agentia g\` 自动维护,也可手工编辑)。
132
+ 1. **目录扫描**:\`createApp({ discover: [...] })\` 启动期按给定顺序扫各目录下的 \`<name>/index.ts\`,default export 为类时以文件夹名为 DI token 注册(见 \`src/main.ts\`)。
133
+ 2. **显式装配**:\`createApp({ providers, system })\`,providers 来自 \`src/registry.ts\` 注册表(由 \`agentia g\` 自动维护,也可手工编辑)。
103
134
 
104
135
  两者二选一或混用。
105
136
 
106
- ## 生成单元
137
+ ## 生成能力
107
138
 
108
139
  \`\`\`bash
109
- agentia g tool my-tool # 工具
110
- agentia g skill my-skill # 技能
111
- agentia g prompt my-prompt # 文本资产(含 asset.md)
112
- agentia g subagent my-agent # 子代理(含 system.md)
140
+ agentia g tool my-tool # → src/tools/my-tool/
141
+ agentia g skill my-skill # → src/skills/my-skill/
142
+ agentia g prompt my-prompt # → src/prompts/my-prompt/(含 asset.md)
143
+ agentia g subagent my-agent # → src/subagents/my-agent/(含 system.md)
113
144
  \`\`\`
114
145
 
115
- 生成的单元在 \`units/<name>/\`,并自动登记到 \`units.ts\`。
146
+ 生成的能力自动登记到 \`src/registry.ts\`。
116
147
 
117
148
  ## 运行
118
149
 
119
- 需要 Anthropic API key:
150
+ 需要 Anthropic API key —— 填进脚手架已生成的 \`.env\` 即可(本文件在 \`.gitignore\` 里):
151
+
152
+ \`\`\`bash
153
+ # .env
154
+ ANTHROPIC_API_KEY=sk-ant-...
155
+ \`\`\`
156
+
157
+ \`\`\`bash
158
+ npm run dev -- "你的问题"
159
+ \`\`\`
160
+
161
+ 也可以用环境变量(适合 CI / 容器)——**真实环境变量优先,不会被 \`.env\` 覆盖**:
120
162
 
121
163
  \`\`\`bash
122
164
  export ANTHROPIC_API_KEY=sk-ant-...
123
165
  npm run dev -- "你的问题"
124
166
  \`\`\`
167
+
168
+ \`.env\` 由 \`src/main.ts\` 首行的 \`loadEnvFile()\` 读取。框架**不会自动读**它 ——
169
+ 读哪个文件、什么时候读由你的启动代码决定(这样「换目录跑」不会悄悄改变行为)。
125
170
  `;
126
171
  }
127
172
  export function projectGitignore() {
128
173
  return `node_modules
129
174
  dist
175
+
176
+ # 本地环境变量(可能含 key)—— 绝不提交
177
+ .env
178
+ .env.local
179
+ `;
180
+ }
181
+ /** 脚手架生成的 .env:填上就能跑,已进 .gitignore */
182
+ export function projectDotEnv() {
183
+ return `# 模型 API key —— 填上后 npm run dev / npm start 直接可用
184
+ # 本文件已被 .gitignore 忽略:不要提交,也不要把 key 写进 README / AGENTS.md
185
+ ANTHROPIC_API_KEY=
186
+ `;
187
+ }
188
+ /** 随脚手架提交的 .env.example:进版本库的变量清单,值一律留空 */
189
+ export function projectDotEnvExample() {
190
+ return `# 复制成 .env 再填值(.env 已 gitignore,不要提交)
191
+ ANTHROPIC_API_KEY=
192
+
193
+ # 可选
194
+ # ANTHROPIC_BASE_URL=https://api.anthropic.com
195
+ # AGENTIA_MODEL=claude-opus-5
130
196
  `;
131
197
  }
132
- // ---------- g 命令单元模板 ----------
198
+ // ---------- g 命令能力模板 ----------
133
199
  export function toolIndexTs(name) {
134
200
  const cls = kebabToPascal(name);
135
201
  const method = kebabToSnake(name);
136
202
  return `import { Tool } from '@migor/agentia';
137
203
 
138
- /** ${name} 工具单元 */
204
+ /** ${name} 工具能力 */
139
205
  export default class ${cls} {
140
206
  @Tool({
141
207
  description: '示例工具:回显输入',
@@ -158,7 +224,7 @@ export function promptIndexTs(name) {
158
224
  const method = kebabToSnake(name);
159
225
  return `import { Prompt, asset } from '@migor/agentia';
160
226
 
161
- /** ${name} 文本资产单元 */
227
+ /** ${name} 文本资产能力 */
162
228
  export default class ${cls} {
163
229
  @Prompt({ description: '${name} 文本资产(描述何时该拉取)' })
164
230
  ${method}(): string {
@@ -178,7 +244,7 @@ export function subagentIndexTs(name) {
178
244
  const method = kebabToSnake(name);
179
245
  return `import { SubAgent, asset } from '@migor/agentia';
180
246
 
181
- /** ${name} 子代理单元 */
247
+ /** ${name} 子代理能力 */
182
248
  export default class ${cls} {
183
249
  @SubAgent({
184
250
  description: '示例子代理:按 system.md 的角色设定独立处理任务',
@@ -207,7 +273,7 @@ export function skillIndexTs(name) {
207
273
  return `import { Skill } from '@migor/agentia';
208
274
  import type { SkillContext } from '@migor/agentia';
209
275
 
210
- /** ${name} 技能单元 */
276
+ /** ${name} 技能能力 */
211
277
  export default class ${cls} {
212
278
  @Skill({
213
279
  description: '示例技能:就给定主题调用 LLM 产出要点',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@migor/cli",
3
- "version": "0.2.1",
4
- "description": "Agentia 框架命令行工具:create 脚手架 + g 单元生成器",
3
+ "version": "0.3.0",
4
+ "description": "Agentia 框架命令行工具:create 脚手架 + g 能力生成 + dev 本地可观测面板(trace inspector)",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "agentia": "./dist/cli.js"
@@ -10,6 +10,11 @@
10
10
  "dist"
11
11
  ],
12
12
  "repository": "retrychx/agentia",
13
+ "homepage": "https://agentia-web.pages.dev",
14
+ "bugs": {
15
+ "url": "https://github.com/retrychx/agentia/issues"
16
+ },
17
+ "license": "MIT",
13
18
  "keywords": [
14
19
  "agentia",
15
20
  "agent",
@@ -24,7 +29,8 @@
24
29
  },
25
30
  "scripts": {
26
31
  "build": "tsc -p tsconfig.json",
27
- "prepublishOnly": "npm run build"
32
+ "test": "node --test \"test/*.test.mjs\"",
33
+ "prepublishOnly": "node ../../scripts/check-release.mjs && npm run build"
28
34
  },
29
35
  "devDependencies": {
30
36
  "@types/node": "^22.0.2",