@aramassa/ai-rules 0.2.2 → 0.3.2
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/artifact/chatmodes/Planning.md +2 -0
- package/artifact/prompts/ai-rules/for_recipe.md +142 -12
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +95 -21
- package/dist/recipeValidator.d.ts +4 -0
- package/dist/recipeValidator.d.ts.map +1 -1
- package/dist/recipeValidator.js +26 -4
- package/package.json +1 -1
|
@@ -44,10 +44,10 @@ AI-rules プロジェクトにおけるレシピファイル(recipe files)
|
|
|
44
44
|
**基本構造の決定**
|
|
45
45
|
```yaml
|
|
46
46
|
config:
|
|
47
|
-
baseDir: [
|
|
47
|
+
baseDir: [出力先ディレクトリ] # オプション - 出力ファイルの配置場所を指定
|
|
48
48
|
recipe:
|
|
49
49
|
- title: "[レシピアイテムのタイトル]"
|
|
50
|
-
out: "[
|
|
50
|
+
out: "[ファイル名のみ]" # baseDirが設定されている場合はファイル名のみ推奨
|
|
51
51
|
# フィルタリング条件
|
|
52
52
|
# 出力設定
|
|
53
53
|
# FrontMatter設定
|
|
@@ -60,6 +60,57 @@ recipe:
|
|
|
60
60
|
- **output**: 出力先とモード設定
|
|
61
61
|
- **frontmatter**: メタデータの管理
|
|
62
62
|
|
|
63
|
+
### ファイル命名規則とbaseDir活用のベストプラクティス
|
|
64
|
+
|
|
65
|
+
#### ファイル命名規則
|
|
66
|
+
|
|
67
|
+
**拡張子ルール**
|
|
68
|
+
- **instructionファイル**: `.instructions.md`
|
|
69
|
+
- **promptファイル**: `.prompt.md`
|
|
70
|
+
- **一般的なドキュメント**: `.md`
|
|
71
|
+
|
|
72
|
+
#### baseDir活用の正しい方法
|
|
73
|
+
|
|
74
|
+
**✅ 推奨: baseDirを出力先ディレクトリに設定**
|
|
75
|
+
```yaml
|
|
76
|
+
config:
|
|
77
|
+
baseDir: .github/instructions # 出力先ディレクトリを指定
|
|
78
|
+
|
|
79
|
+
recipe:
|
|
80
|
+
- title: "TypeScript Guidelines"
|
|
81
|
+
out: "typescript-rules.instructions.md" # ファイル名のみ
|
|
82
|
+
type: coding-rules
|
|
83
|
+
language: typescript
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**❌ 避けるべき: baseDirをソースディレクトリに設定して複雑なパス指定**
|
|
87
|
+
```yaml
|
|
88
|
+
config:
|
|
89
|
+
baseDir: artifact/instructions # ソースディレクトリ指定は混乱の原因
|
|
90
|
+
|
|
91
|
+
recipe:
|
|
92
|
+
- title: "TypeScript Guidelines"
|
|
93
|
+
out: "./.github/instructions/typescript-rules.md" # 複雑なパス指定
|
|
94
|
+
type: coding-rules
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### 出力パス設定のベストプラクティス
|
|
98
|
+
|
|
99
|
+
**シンプルなパス管理**
|
|
100
|
+
- `baseDir`: 出力先ディレクトリを指定
|
|
101
|
+
- `out`: ファイル名のみ(拡張子含む)を指定
|
|
102
|
+
- パスの複雑な指定は避ける
|
|
103
|
+
|
|
104
|
+
**環境変数展開の活用**
|
|
105
|
+
```yaml
|
|
106
|
+
config:
|
|
107
|
+
baseDir: ~/.config/vscode-prompts # チルダ展開や環境変数展開に対応
|
|
108
|
+
|
|
109
|
+
recipe:
|
|
110
|
+
- title: "Custom Rules"
|
|
111
|
+
out: "custom-rules.instructions.md"
|
|
112
|
+
```
|
|
113
|
+
|
|
63
114
|
#### 手順3: フィルタリング条件の設定
|
|
64
115
|
|
|
65
116
|
**標準フィルター**
|
|
@@ -86,8 +137,25 @@ filters:
|
|
|
86
137
|
|
|
87
138
|
**出力ファイル設定**
|
|
88
139
|
```yaml
|
|
89
|
-
out: "
|
|
90
|
-
mode: overwrite
|
|
140
|
+
out: "filename.instructions.md" # ファイル名のみ(baseDirが設定されている場合)
|
|
141
|
+
mode: overwrite # overwrite(デフォルト)、append、prepend
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**パス指定のパターン**
|
|
145
|
+
```yaml
|
|
146
|
+
# パターン1: baseDir + ファイル名のみ(推奨)
|
|
147
|
+
config:
|
|
148
|
+
baseDir: .github/instructions
|
|
149
|
+
recipe:
|
|
150
|
+
- out: "typescript.instructions.md"
|
|
151
|
+
|
|
152
|
+
# パターン2: 絶対パスまたは相対パス(baseDirを無視)
|
|
153
|
+
recipe:
|
|
154
|
+
- out: "./docs/typescript.md"
|
|
155
|
+
|
|
156
|
+
# パターン3: 環境変数展開
|
|
157
|
+
recipe:
|
|
158
|
+
- out: "$HOME/.vscode/prompts/typescript.instructions.md"
|
|
91
159
|
```
|
|
92
160
|
|
|
93
161
|
**複数アイテムでの同一ファイル出力**
|
|
@@ -145,11 +213,11 @@ recipe:
|
|
|
145
213
|
# Generated by ai-rules prompt system
|
|
146
214
|
|
|
147
215
|
config:
|
|
148
|
-
baseDir: [
|
|
216
|
+
baseDir: [OUTPUT_DIRECTORY] # 出力先ディレクトリを指定
|
|
149
217
|
|
|
150
218
|
recipe:
|
|
151
219
|
- title: "[DOCUMENT_TITLE]"
|
|
152
|
-
out: "[
|
|
220
|
+
out: "[FILENAME].instructions.md" # instructionファイルの場合
|
|
153
221
|
type: [INSTRUCTION_TYPE]
|
|
154
222
|
language: [TARGET_LANGUAGE]
|
|
155
223
|
frontmatter:
|
|
@@ -200,6 +268,16 @@ recipe:
|
|
|
200
268
|
- [ ] **フィルター整合性**: 指定したフィルターに対応するファイルが存在する
|
|
201
269
|
- [ ] **パス有効性**: 出力先パスが適切で、ディレクトリが存在または作成可能
|
|
202
270
|
|
|
271
|
+
#### ファイル出力の品質チェック
|
|
272
|
+
|
|
273
|
+
- [ ] **baseDir設定**: 出力先ディレクトリが正しく設定されている
|
|
274
|
+
- [ ] **出力パス**: outフィールドがファイル名のみになっている(baseDirを活用する場合)
|
|
275
|
+
- [ ] **拡張子**: ファイルタイプに応じた適切な拡張子を使用
|
|
276
|
+
- instructionファイル: `.instructions.md`
|
|
277
|
+
- promptファイル: `.prompt.md`
|
|
278
|
+
- 一般ドキュメント: `.md`
|
|
279
|
+
- [ ] **パス複雑性**: 不要な相対パス指定を避けている
|
|
280
|
+
|
|
203
281
|
#### 機能性の検証
|
|
204
282
|
|
|
205
283
|
- [ ] **フィルタリング**: 期待するファイル群が正しく抽出される
|
|
@@ -221,11 +299,11 @@ recipe:
|
|
|
221
299
|
```yaml
|
|
222
300
|
# Basic project setup
|
|
223
301
|
config:
|
|
224
|
-
baseDir:
|
|
302
|
+
baseDir: .github/instructions # 出力先ディレクトリ
|
|
225
303
|
|
|
226
304
|
recipe:
|
|
227
305
|
- title: "Project Guidelines"
|
|
228
|
-
out: "
|
|
306
|
+
out: "project-guidelines.instructions.md" # ファイル名のみ
|
|
229
307
|
type: planning
|
|
230
308
|
frontmatter:
|
|
231
309
|
description: "Basic project development guidelines"
|
|
@@ -236,12 +314,15 @@ recipe:
|
|
|
236
314
|
|
|
237
315
|
```yaml
|
|
238
316
|
# TypeScript project comprehensive rules
|
|
317
|
+
config:
|
|
318
|
+
baseDir: .github/instructions
|
|
319
|
+
|
|
239
320
|
recipe:
|
|
240
321
|
- import: :basic
|
|
241
322
|
- import: :typescript
|
|
242
323
|
|
|
243
324
|
- title: "Custom TypeScript Rules"
|
|
244
|
-
out: "
|
|
325
|
+
out: "custom-typescript.instructions.md" # ファイル名のみ
|
|
245
326
|
type: coding-rules
|
|
246
327
|
language: typescript
|
|
247
328
|
filters:
|
|
@@ -258,21 +339,24 @@ recipe:
|
|
|
258
339
|
|
|
259
340
|
```yaml
|
|
260
341
|
# Generate multiple specialized documents
|
|
342
|
+
config:
|
|
343
|
+
baseDir: ./docs
|
|
344
|
+
|
|
261
345
|
recipe:
|
|
262
346
|
- title: "Development Guidelines"
|
|
263
|
-
out: "
|
|
347
|
+
out: "development.instructions.md" # ファイル名のみ
|
|
264
348
|
type: coding-rules
|
|
265
349
|
filters:
|
|
266
350
|
category: development
|
|
267
351
|
|
|
268
352
|
- title: "Testing Guidelines"
|
|
269
|
-
out: "
|
|
353
|
+
out: "testing.instructions.md" # ファイル名のみ
|
|
270
354
|
type: test
|
|
271
355
|
filters:
|
|
272
356
|
category: best-practices
|
|
273
357
|
|
|
274
358
|
- title: "Deployment Guidelines"
|
|
275
|
-
out: "
|
|
359
|
+
out: "deployment.instructions.md" # ファイル名のみ
|
|
276
360
|
filters:
|
|
277
361
|
category: configuration
|
|
278
362
|
focus: deployment
|
|
@@ -301,9 +385,13 @@ recipe:
|
|
|
301
385
|
|
|
302
386
|
**フロントエンド中心**
|
|
303
387
|
```yaml
|
|
388
|
+
config:
|
|
389
|
+
baseDir: .github/instructions
|
|
390
|
+
|
|
304
391
|
recipe:
|
|
305
392
|
- import: :typescript
|
|
306
393
|
- title: "React Guidelines"
|
|
394
|
+
out: "react-guidelines.instructions.md"
|
|
307
395
|
type: coding-rules
|
|
308
396
|
language: [typescript, javascript]
|
|
309
397
|
filters:
|
|
@@ -313,9 +401,13 @@ recipe:
|
|
|
313
401
|
|
|
314
402
|
**バックエンド中心**
|
|
315
403
|
```yaml
|
|
404
|
+
config:
|
|
405
|
+
baseDir: .github/instructions
|
|
406
|
+
|
|
316
407
|
recipe:
|
|
317
408
|
- import: :typescript
|
|
318
409
|
- title: "API Development"
|
|
410
|
+
out: "api-development.instructions.md"
|
|
319
411
|
type: coding-rules
|
|
320
412
|
filters:
|
|
321
413
|
category: backend
|
|
@@ -324,10 +416,14 @@ recipe:
|
|
|
324
416
|
|
|
325
417
|
**フルスタック**
|
|
326
418
|
```yaml
|
|
419
|
+
config:
|
|
420
|
+
baseDir: .github/instructions
|
|
421
|
+
|
|
327
422
|
recipe:
|
|
328
423
|
- import: :basic
|
|
329
424
|
- import: :typescript
|
|
330
425
|
- title: "Full Stack Guidelines"
|
|
426
|
+
out: "fullstack-guidelines.instructions.md"
|
|
331
427
|
type: coding-rules
|
|
332
428
|
filters:
|
|
333
429
|
category: [frontend, backend]
|
|
@@ -335,6 +431,40 @@ recipe:
|
|
|
335
431
|
|
|
336
432
|
### トラブルシューティング
|
|
337
433
|
|
|
434
|
+
#### baseDir設定に関する一般的な問題
|
|
435
|
+
|
|
436
|
+
**問題1: 意図しない場所にファイルが出力される**
|
|
437
|
+
```yaml
|
|
438
|
+
# ❌ 問題のある例
|
|
439
|
+
config:
|
|
440
|
+
baseDir: instructions # ソースディレクトリを指定
|
|
441
|
+
|
|
442
|
+
recipe:
|
|
443
|
+
- out: "./.github/instructions/file.md" # 複雑なパス指定
|
|
444
|
+
# 結果: instructions/.github/instructions/file.md に出力
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
```yaml
|
|
448
|
+
# ✅ 修正例
|
|
449
|
+
config:
|
|
450
|
+
baseDir: .github/instructions # 出力先ディレクトリを指定
|
|
451
|
+
|
|
452
|
+
recipe:
|
|
453
|
+
- out: "file.instructions.md" # ファイル名のみ
|
|
454
|
+
# 結果: .github/instructions/file.instructions.md に出力
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**問題2: ファイル拡張子の規則が統一されていない**
|
|
458
|
+
```yaml
|
|
459
|
+
# ❌ 問題のある例
|
|
460
|
+
recipe:
|
|
461
|
+
- out: "typescript-rules.md" # instructionファイルなのに .md
|
|
462
|
+
|
|
463
|
+
# ✅ 修正例
|
|
464
|
+
recipe:
|
|
465
|
+
- out: "typescript-rules.instructions.md" # 正しい拡張子
|
|
466
|
+
```
|
|
467
|
+
|
|
338
468
|
#### 一般的な問題と解決法
|
|
339
469
|
|
|
340
470
|
**フィルタリング結果が空**
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAqjBA;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBpG"}
|
package/dist/cli.js
CHANGED
|
@@ -17683,9 +17683,6 @@ function requireDist () {
|
|
|
17683
17683
|
var distExports = requireDist();
|
|
17684
17684
|
var addFormats = /*@__PURE__*/getDefaultExportFromCjs(distExports);
|
|
17685
17685
|
|
|
17686
|
-
// Get the current file's directory for schema loading
|
|
17687
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
17688
|
-
const __dirname = path.dirname(__filename);
|
|
17689
17686
|
class RecipeValidator {
|
|
17690
17687
|
constructor() {
|
|
17691
17688
|
this.ajv = new Ajv({
|
|
@@ -17697,7 +17694,8 @@ class RecipeValidator {
|
|
|
17697
17694
|
}
|
|
17698
17695
|
async initialize() {
|
|
17699
17696
|
try {
|
|
17700
|
-
const
|
|
17697
|
+
const packageRoot = this.findPackageRoot();
|
|
17698
|
+
const schemaPath = path.join(packageRoot, 'schemas/recipe.schema.json');
|
|
17701
17699
|
const schemaContent = await fs.readFile(schemaPath, 'utf-8');
|
|
17702
17700
|
this.schema = JSON.parse(schemaContent);
|
|
17703
17701
|
this.ajv.addSchema(this.schema, 'recipe');
|
|
@@ -17715,6 +17713,29 @@ class RecipeValidator {
|
|
|
17715
17713
|
this.ajv.addSchema(this.schema, 'recipe');
|
|
17716
17714
|
}
|
|
17717
17715
|
}
|
|
17716
|
+
/**
|
|
17717
|
+
* Finds the package root directory by looking for package.json
|
|
17718
|
+
*/
|
|
17719
|
+
findPackageRoot() {
|
|
17720
|
+
// For ES modules, get current file path
|
|
17721
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
17722
|
+
let dir = path.dirname(currentFile);
|
|
17723
|
+
// Walk up directory tree looking for package.json
|
|
17724
|
+
while (dir !== path.dirname(dir)) {
|
|
17725
|
+
const packageJsonPath = path.join(dir, 'package.json');
|
|
17726
|
+
try {
|
|
17727
|
+
// Use synchronous check since this is initialization
|
|
17728
|
+
fsSync.accessSync(packageJsonPath);
|
|
17729
|
+
return dir;
|
|
17730
|
+
}
|
|
17731
|
+
catch {
|
|
17732
|
+
// Continue searching
|
|
17733
|
+
}
|
|
17734
|
+
dir = path.dirname(dir);
|
|
17735
|
+
}
|
|
17736
|
+
// Fallback to current working directory
|
|
17737
|
+
return process.cwd();
|
|
17738
|
+
}
|
|
17718
17739
|
validateRecipe(recipeData) {
|
|
17719
17740
|
const result = {
|
|
17720
17741
|
isValid: true,
|
|
@@ -17954,6 +17975,16 @@ function resolveDefaultSrcDir(providedSrc) {
|
|
|
17954
17975
|
const packageRoot = findPackageRoot();
|
|
17955
17976
|
return path.join(packageRoot, 'artifact');
|
|
17956
17977
|
}
|
|
17978
|
+
/**
|
|
17979
|
+
* Resolves source directory for a recipe item following priority order:
|
|
17980
|
+
* 1. CLI --src option (highest priority)
|
|
17981
|
+
* 2. Recipe item src field (medium priority)
|
|
17982
|
+
* 3. Import-level src field (medium priority)
|
|
17983
|
+
* 4. Default package artifact/ directory (lowest priority)
|
|
17984
|
+
*/
|
|
17985
|
+
function resolveItemSrcDir(cliSrc, itemSrc, importSrc) {
|
|
17986
|
+
return cliSrc || itemSrc || importSrc || resolveDefaultSrcDir();
|
|
17987
|
+
}
|
|
17957
17988
|
/**
|
|
17958
17989
|
* Resolves output path with baseDir support following priority order:
|
|
17959
17990
|
* 1. CLI baseDir option (highest priority)
|
|
@@ -18103,24 +18134,51 @@ async function expandRecipeImports(items, currentPath, debugLogger, visited = ne
|
|
|
18103
18134
|
throw new Error(`Invalid imported recipe file '${importPath}': 'recipe' array not found`);
|
|
18104
18135
|
}
|
|
18105
18136
|
debugLogger?.log(`Import contains ${importData.recipe.length} items`);
|
|
18106
|
-
// Check if this import item has
|
|
18137
|
+
// Check if this import item has import-level configurations
|
|
18107
18138
|
const importLevelBaseDir = item.baseDir;
|
|
18139
|
+
const importLevelSrc = item.src;
|
|
18140
|
+
const importLevelVariables = item.variables;
|
|
18108
18141
|
if (importLevelBaseDir) {
|
|
18109
18142
|
debugLogger?.log(`Import has baseDir: ${importLevelBaseDir}`);
|
|
18110
18143
|
}
|
|
18144
|
+
if (importLevelSrc) {
|
|
18145
|
+
debugLogger?.log(`Import has src: ${importLevelSrc}`);
|
|
18146
|
+
}
|
|
18147
|
+
if (importLevelVariables) {
|
|
18148
|
+
debugLogger?.log(`Import has variables:`, importLevelVariables);
|
|
18149
|
+
}
|
|
18111
18150
|
// Recursively expand imports in the imported recipe
|
|
18112
18151
|
debugLogger?.time(`Expanding nested imports in: ${resolvedImportPath}`);
|
|
18113
18152
|
const expandedImported = await expandRecipeImports(importData.recipe, resolvedImportPath, debugLogger, newVisited, imported, depth + 1);
|
|
18114
18153
|
debugLogger?.timeEnd(`Expanding nested imports in: ${resolvedImportPath}`);
|
|
18115
18154
|
debugLogger?.log(`Nested expansion yielded ${expandedImported.length} items`);
|
|
18116
|
-
//
|
|
18117
|
-
if (importLevelBaseDir) {
|
|
18155
|
+
// Apply import-level configurations to all expanded items
|
|
18156
|
+
if (importLevelBaseDir || importLevelSrc || importLevelVariables) {
|
|
18118
18157
|
expandedImported.forEach(expandedItem => {
|
|
18119
|
-
//
|
|
18120
|
-
if (!expandedItem._importBaseDir) {
|
|
18158
|
+
// Apply baseDir if specified (only if not already set to preserve nested import priority)
|
|
18159
|
+
if (importLevelBaseDir && !expandedItem._importBaseDir) {
|
|
18121
18160
|
expandedItem._importBaseDir = importLevelBaseDir;
|
|
18122
18161
|
debugLogger?.log(`Tagged item '${expandedItem.title || expandedItem.out || 'untitled'}' with import baseDir: ${importLevelBaseDir}`);
|
|
18123
18162
|
}
|
|
18163
|
+
// Apply src if specified (only if not already set to preserve nested import priority)
|
|
18164
|
+
if (importLevelSrc && !expandedItem._importSrc) {
|
|
18165
|
+
expandedItem._importSrc = importLevelSrc;
|
|
18166
|
+
debugLogger?.log(`Tagged item '${expandedItem.title || expandedItem.out || 'untitled'}' with import src: ${importLevelSrc}`);
|
|
18167
|
+
}
|
|
18168
|
+
// Apply variables if specified (merge with existing variables, with import-level taking priority)
|
|
18169
|
+
if (importLevelVariables) {
|
|
18170
|
+
if (!expandedItem._importVariables) {
|
|
18171
|
+
expandedItem._importVariables = { ...importLevelVariables };
|
|
18172
|
+
}
|
|
18173
|
+
else {
|
|
18174
|
+
// Merge variables, with import-level taking priority over nested imports
|
|
18175
|
+
expandedItem._importVariables = {
|
|
18176
|
+
...expandedItem._importVariables,
|
|
18177
|
+
...importLevelVariables
|
|
18178
|
+
};
|
|
18179
|
+
}
|
|
18180
|
+
debugLogger?.log(`Tagged item '${expandedItem.title || expandedItem.out || 'untitled'}' with import variables:`, expandedItem._importVariables);
|
|
18181
|
+
}
|
|
18124
18182
|
});
|
|
18125
18183
|
}
|
|
18126
18184
|
// Add all expanded items from the import
|
|
@@ -18625,11 +18683,11 @@ async function handleExtractCommand(options) {
|
|
|
18625
18683
|
await validateRecipeFilesExist(options.recipe);
|
|
18626
18684
|
if (options.recipe.length === 1) {
|
|
18627
18685
|
// Single recipe - maintain backward compatibility
|
|
18628
|
-
await processRecipe(options.recipe[0], extractOptions, new ContentTracker(), debugLogger, options.baseDir, options.out);
|
|
18686
|
+
await processRecipe(options.recipe[0], extractOptions, new ContentTracker(), debugLogger, options.baseDir, options.out, options.src);
|
|
18629
18687
|
}
|
|
18630
18688
|
else {
|
|
18631
18689
|
// Multiple recipes - process in order with auto-append
|
|
18632
|
-
await processMultipleRecipes(options.recipe, extractOptions, debugLogger, options.baseDir, options.out);
|
|
18690
|
+
await processMultipleRecipes(options.recipe, extractOptions, debugLogger, options.baseDir, options.out, options.src);
|
|
18633
18691
|
}
|
|
18634
18692
|
}
|
|
18635
18693
|
else {
|
|
@@ -18655,13 +18713,13 @@ async function handleStatsCommand(options) {
|
|
|
18655
18713
|
/**
|
|
18656
18714
|
* Processes multiple recipe files in the specified order
|
|
18657
18715
|
*/
|
|
18658
|
-
async function processMultipleRecipes(recipePaths, baseOptions, debugLogger, cliBaseDir, cliOutFile) {
|
|
18716
|
+
async function processMultipleRecipes(recipePaths, baseOptions, debugLogger, cliBaseDir, cliOutFile, cliSrc) {
|
|
18659
18717
|
const contentTracker = new ContentTracker();
|
|
18660
18718
|
debugLogger.log(`Processing ${recipePaths.length} recipes in order`);
|
|
18661
18719
|
for (const recipePath of recipePaths) {
|
|
18662
18720
|
try {
|
|
18663
18721
|
debugLogger.log(`Starting processing of recipe: ${recipePath}`);
|
|
18664
|
-
await processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile);
|
|
18722
|
+
await processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile, cliSrc);
|
|
18665
18723
|
debugLogger.log(`Completed processing of recipe: ${recipePath}`);
|
|
18666
18724
|
}
|
|
18667
18725
|
catch (error) {
|
|
@@ -18770,7 +18828,7 @@ async function processFrontmatterInheritance(frontmatter, srcDir, types, languag
|
|
|
18770
18828
|
/**
|
|
18771
18829
|
* Processes a recipe file with multiple extract operations
|
|
18772
18830
|
*/
|
|
18773
|
-
async function processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile) {
|
|
18831
|
+
async function processRecipe(recipePath, baseOptions, contentTracker, debugLogger, cliBaseDir, cliOutFile, cliSrc) {
|
|
18774
18832
|
const resolvedPath = resolveRecipePath(recipePath);
|
|
18775
18833
|
debugLogger?.log(`Processing recipe at path: ${resolvedPath}`);
|
|
18776
18834
|
try {
|
|
@@ -18853,18 +18911,34 @@ async function processRecipe(recipePath, baseOptions, contentTracker, debugLogge
|
|
|
18853
18911
|
baseAttrFilters: attrFilters,
|
|
18854
18912
|
itemFilters: item.filters || 'none'
|
|
18855
18913
|
});
|
|
18856
|
-
// Resolve template variables for this item (merge
|
|
18914
|
+
// Resolve template variables for this item (merge import variables, recipe item variables, and CLI variables)
|
|
18857
18915
|
let itemVars = vars;
|
|
18858
|
-
if (item.variables) {
|
|
18916
|
+
if (item.variables || item._importVariables) {
|
|
18859
18917
|
const cliVariables = vars ? VariableResolver.parseCliVariables(vars) : {};
|
|
18860
|
-
const
|
|
18918
|
+
const importVariables = item._importVariables || {};
|
|
18919
|
+
const itemVariables = item.variables || {};
|
|
18920
|
+
// Merge with priority: CLI > item > import
|
|
18921
|
+
const mergedVariables = { ...importVariables, ...itemVariables, ...cliVariables };
|
|
18861
18922
|
itemVars = Object.entries(mergedVariables)
|
|
18862
18923
|
.map(([key, value]) => `${key}=${value}`)
|
|
18863
18924
|
.join(',');
|
|
18864
|
-
debugLogger?.log(`Merged variables for item ${index + 1}:`,
|
|
18925
|
+
debugLogger?.log(`Merged variables for item ${index + 1}:`, {
|
|
18926
|
+
importVariables,
|
|
18927
|
+
itemVariables,
|
|
18928
|
+
cliVariables,
|
|
18929
|
+
merged: mergedVariables
|
|
18930
|
+
});
|
|
18865
18931
|
}
|
|
18932
|
+
// Resolve source directory for this item with priority: CLI --src > item.src > import.src > default
|
|
18933
|
+
const itemSrcDir = resolveItemSrcDir(cliSrc, item.src, item._importSrc);
|
|
18934
|
+
debugLogger?.log(`Resolved source directory for item ${index + 1}:`, {
|
|
18935
|
+
cliSrc,
|
|
18936
|
+
itemSrc: item.src,
|
|
18937
|
+
importSrc: item._importSrc,
|
|
18938
|
+
resolved: itemSrcDir
|
|
18939
|
+
});
|
|
18866
18940
|
debugLogger?.time(`Content generation for item ${index + 1}`);
|
|
18867
|
-
const filtered = await loadAndFilterFiles(
|
|
18941
|
+
const filtered = await loadAndFilterFiles(itemSrcDir, itemTypes, itemLanguages, combinedAttrFilters, debugLogger);
|
|
18868
18942
|
const merged = filtered.map((f) => f.content.trim()).join("\n\n");
|
|
18869
18943
|
const contentWithTitle = itemTitle ? `# ${itemTitle}\n\n${merged}` : merged;
|
|
18870
18944
|
debugLogger?.timeEnd(`Content generation for item ${index + 1}`);
|
|
@@ -18895,10 +18969,10 @@ async function processRecipe(recipePath, baseOptions, contentTracker, debugLogge
|
|
|
18895
18969
|
}
|
|
18896
18970
|
// Process frontmatter inheritance (@ syntax)
|
|
18897
18971
|
debugLogger?.time(`Frontmatter inheritance processing for item ${index + 1}`);
|
|
18898
|
-
const processedFrontmatter = await processFrontmatterInheritance(item.frontmatter,
|
|
18972
|
+
const processedFrontmatter = await processFrontmatterInheritance(item.frontmatter, itemSrcDir, itemTypes, itemLanguages, combinedAttrFilters, debugLogger);
|
|
18899
18973
|
debugLogger?.timeEnd(`Frontmatter inheritance processing for item ${index + 1}`);
|
|
18900
18974
|
const options = {
|
|
18901
|
-
srcDir:
|
|
18975
|
+
srcDir: itemSrcDir,
|
|
18902
18976
|
outFile: outputFile,
|
|
18903
18977
|
types: itemTypes,
|
|
18904
18978
|
languages: itemLanguages,
|
|
@@ -8,6 +8,10 @@ export declare class RecipeValidator {
|
|
|
8
8
|
private schema;
|
|
9
9
|
constructor();
|
|
10
10
|
initialize(): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Finds the package root directory by looking for package.json
|
|
13
|
+
*/
|
|
14
|
+
private findPackageRoot;
|
|
11
15
|
validateRecipe(recipeData: any): ValidationResult;
|
|
12
16
|
private formatSchemaError;
|
|
13
17
|
private getHelpfulMessageForProperty;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipeValidator.d.ts","sourceRoot":"","sources":["../src/recipeValidator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recipeValidator.d.ts","sourceRoot":"","sources":["../src/recipeValidator.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,MAAM,CAAM;;IAWd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBjC;;OAEG;IACH,OAAO,CAAC,eAAe;IAsBvB,cAAc,CAAC,UAAU,EAAE,GAAG,GAAG,gBAAgB;IA0CjD,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,4BAA4B;IAYpC,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;CAyC5B;AAKD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC,CAMnE"}
|
package/dist/recipeValidator.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import Ajv from 'ajv';
|
|
2
2
|
import addFormats from 'ajv-formats';
|
|
3
3
|
import fs from 'fs/promises';
|
|
4
|
+
import fsSync from 'fs';
|
|
4
5
|
import path from 'path';
|
|
5
6
|
import { fileURLToPath } from 'url';
|
|
6
|
-
// Get the current file's directory for schema loading
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = path.dirname(__filename);
|
|
9
7
|
export class RecipeValidator {
|
|
10
8
|
constructor() {
|
|
11
9
|
this.ajv = new Ajv({
|
|
@@ -17,7 +15,8 @@ export class RecipeValidator {
|
|
|
17
15
|
}
|
|
18
16
|
async initialize() {
|
|
19
17
|
try {
|
|
20
|
-
const
|
|
18
|
+
const packageRoot = this.findPackageRoot();
|
|
19
|
+
const schemaPath = path.join(packageRoot, 'schemas/recipe.schema.json');
|
|
21
20
|
const schemaContent = await fs.readFile(schemaPath, 'utf-8');
|
|
22
21
|
this.schema = JSON.parse(schemaContent);
|
|
23
22
|
this.ajv.addSchema(this.schema, 'recipe');
|
|
@@ -35,6 +34,29 @@ export class RecipeValidator {
|
|
|
35
34
|
this.ajv.addSchema(this.schema, 'recipe');
|
|
36
35
|
}
|
|
37
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Finds the package root directory by looking for package.json
|
|
39
|
+
*/
|
|
40
|
+
findPackageRoot() {
|
|
41
|
+
// For ES modules, get current file path
|
|
42
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
43
|
+
let dir = path.dirname(currentFile);
|
|
44
|
+
// Walk up directory tree looking for package.json
|
|
45
|
+
while (dir !== path.dirname(dir)) {
|
|
46
|
+
const packageJsonPath = path.join(dir, 'package.json');
|
|
47
|
+
try {
|
|
48
|
+
// Use synchronous check since this is initialization
|
|
49
|
+
fsSync.accessSync(packageJsonPath);
|
|
50
|
+
return dir;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Continue searching
|
|
54
|
+
}
|
|
55
|
+
dir = path.dirname(dir);
|
|
56
|
+
}
|
|
57
|
+
// Fallback to current working directory
|
|
58
|
+
return process.cwd();
|
|
59
|
+
}
|
|
38
60
|
validateRecipe(recipeData) {
|
|
39
61
|
const result = {
|
|
40
62
|
isValid: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aramassa/ai-rules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "This repository collects guidelines and instructions for developing AI agents. It contains documents covering communication rules, coding standards, testing strategies, and general operational practices.",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"packages/extract",
|