instrux 0.1.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/README.md +279 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +186 -0
- package/dist/cli.js.map +1 -0
- package/dist/compiler.d.ts +35 -0
- package/dist/compiler.d.ts.map +1 -0
- package/dist/compiler.js +218 -0
- package/dist/compiler.js.map +1 -0
- package/dist/engine.d.ts +39 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +229 -0
- package/dist/engine.js.map +1 -0
- package/dist/frontmatter.d.ts +26 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +122 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +34 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +254 -0
- package/dist/init.js.map +1 -0
- package/dist/types.d.ts +104 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
package/dist/compiler.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* instrux — Recursive Handlebars compiler.
|
|
4
|
+
*
|
|
5
|
+
* Compiles an entry template by resolving {{tag}}, {{file}}, and {{tagged}}
|
|
6
|
+
* helpers recursively, producing a single merged output document.
|
|
7
|
+
*
|
|
8
|
+
* Compilation pipeline:
|
|
9
|
+
* 1. Scan sources → parse frontmatter → build tag index
|
|
10
|
+
* 2. Starting from the entry file, compile as Handlebars template
|
|
11
|
+
* 3. Helpers resolve tags/files → each is itself compiled (recursion)
|
|
12
|
+
* 4. Cycle detection via a compile stack
|
|
13
|
+
* 5. Emit final output with optional frontmatter passthrough
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
49
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
50
|
+
};
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.InstruxCompiler = void 0;
|
|
53
|
+
const fs = __importStar(require("fs-extra"));
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
56
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
57
|
+
const frontmatter_1 = require("./frontmatter");
|
|
58
|
+
class InstruxCompiler {
|
|
59
|
+
constructor(rootDir, config) {
|
|
60
|
+
this.compileStack = new Set();
|
|
61
|
+
this.compiledFiles = new Set();
|
|
62
|
+
this.tagsUsed = new Set();
|
|
63
|
+
this.rootDir = rootDir;
|
|
64
|
+
this.config = config;
|
|
65
|
+
}
|
|
66
|
+
// ── Public API ───────────────────────────────────────────
|
|
67
|
+
async compile() {
|
|
68
|
+
if (!this.config.entry) {
|
|
69
|
+
throw new Error('No "entry" field in agent config. Use "files" for simple merge mode.');
|
|
70
|
+
}
|
|
71
|
+
if (!this.config.sources || this.config.sources.length === 0) {
|
|
72
|
+
throw new Error('No "sources" patterns defined. Add source globs to agent config.');
|
|
73
|
+
}
|
|
74
|
+
// 1. Build the source index
|
|
75
|
+
console.log(' 📑 Scanning sources...');
|
|
76
|
+
this.index = await (0, frontmatter_1.buildSourceIndex)(this.rootDir, this.config.sources);
|
|
77
|
+
console.log(` Found ${this.index.files.length} source files, ${this.index.tags.size} unique tags`);
|
|
78
|
+
// 2. Compile starting from entry
|
|
79
|
+
console.log(' 🔧 Compiling templates...');
|
|
80
|
+
this.compileStack.clear();
|
|
81
|
+
this.compiledFiles.clear();
|
|
82
|
+
this.tagsUsed.clear();
|
|
83
|
+
const entryPath = this.config.entry.replace(/\\/g, '/');
|
|
84
|
+
const body = this.compileFile(entryPath);
|
|
85
|
+
// 3. Handle output frontmatter
|
|
86
|
+
let output = '';
|
|
87
|
+
const fmMode = this.config.frontmatter?.output ?? 'strip';
|
|
88
|
+
if (fmMode === 'preserve') {
|
|
89
|
+
const entrySource = this.index.paths.get(entryPath);
|
|
90
|
+
if (entrySource) {
|
|
91
|
+
const cleanFm = (0, frontmatter_1.stripInstruxMeta)(entrySource.frontmatter);
|
|
92
|
+
output += (0, frontmatter_1.serializeFrontmatter)(cleanFm);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
output += body;
|
|
96
|
+
// Ensure trailing newline
|
|
97
|
+
if (!output.endsWith('\n'))
|
|
98
|
+
output += '\n';
|
|
99
|
+
return {
|
|
100
|
+
output,
|
|
101
|
+
filesCompiled: this.compiledFiles.size,
|
|
102
|
+
tagsUsed: [...this.tagsUsed],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// ── Recursive file compilation ───────────────────────────
|
|
106
|
+
compileFile(relPath) {
|
|
107
|
+
const normalised = relPath.replace(/\\/g, '/');
|
|
108
|
+
// Cycle detection
|
|
109
|
+
if (this.compileStack.has(normalised)) {
|
|
110
|
+
const chain = [...this.compileStack, normalised].join(' → ');
|
|
111
|
+
throw new Error(`Circular reference detected:\n ${chain}`);
|
|
112
|
+
}
|
|
113
|
+
this.compileStack.add(normalised);
|
|
114
|
+
this.compiledFiles.add(normalised);
|
|
115
|
+
// Resolve content — from index or from disk
|
|
116
|
+
let content;
|
|
117
|
+
const indexed = this.index.paths.get(normalised);
|
|
118
|
+
if (indexed) {
|
|
119
|
+
content = indexed.content;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// File not in source index — try reading directly
|
|
123
|
+
const absPath = path.join(this.rootDir, normalised);
|
|
124
|
+
if (!fs.pathExistsSync(absPath)) {
|
|
125
|
+
throw new Error(`File not found: ${normalised}`);
|
|
126
|
+
}
|
|
127
|
+
const raw = fs.readFileSync(absPath, 'utf-8');
|
|
128
|
+
const parsed = (0, gray_matter_1.default)(raw);
|
|
129
|
+
content = parsed.content;
|
|
130
|
+
}
|
|
131
|
+
// Create a sandboxed Handlebars instance
|
|
132
|
+
const hbs = handlebars_1.default.create();
|
|
133
|
+
this.registerHelpers(hbs);
|
|
134
|
+
// Compile as Handlebars template (noEscape: markdown, not HTML)
|
|
135
|
+
const template = hbs.compile(content, { noEscape: true });
|
|
136
|
+
const rendered = template({
|
|
137
|
+
agent: {
|
|
138
|
+
name: this.config.name,
|
|
139
|
+
description: this.config.description,
|
|
140
|
+
},
|
|
141
|
+
meta: indexed?.frontmatter ?? {},
|
|
142
|
+
});
|
|
143
|
+
this.compileStack.delete(normalised);
|
|
144
|
+
return rendered;
|
|
145
|
+
}
|
|
146
|
+
// ── Handlebars helpers ───────────────────────────────────
|
|
147
|
+
registerHelpers(hbs) {
|
|
148
|
+
const self = this;
|
|
149
|
+
const sep = this.config.mergeSettings.addSeparators
|
|
150
|
+
? `\n${this.config.mergeSettings.separatorStyle}\n\n`
|
|
151
|
+
: '\n\n';
|
|
152
|
+
/**
|
|
153
|
+
* {{tag "tagname"}}
|
|
154
|
+
*
|
|
155
|
+
* Include all files matching the given tag, sorted by instrux.order.
|
|
156
|
+
* Each file is recursively compiled.
|
|
157
|
+
*/
|
|
158
|
+
hbs.registerHelper('tag', function (tagName) {
|
|
159
|
+
self.tagsUsed.add(tagName);
|
|
160
|
+
const files = self.index.tags.get(tagName);
|
|
161
|
+
if (!files || files.length === 0) {
|
|
162
|
+
console.log(` ⚠ Tag "${tagName}" matched 0 files`);
|
|
163
|
+
return '';
|
|
164
|
+
}
|
|
165
|
+
const sorted = (0, frontmatter_1.sortSourceFiles)(files);
|
|
166
|
+
const rendered = sorted.map(f => self.compileFile(f.path));
|
|
167
|
+
return new hbs.SafeString(rendered.join(sep));
|
|
168
|
+
});
|
|
169
|
+
/**
|
|
170
|
+
* {{file "path/to/file.md"}}
|
|
171
|
+
*
|
|
172
|
+
* Include a specific file by path. Recursively compiled.
|
|
173
|
+
*/
|
|
174
|
+
hbs.registerHelper('file', function (filePath) {
|
|
175
|
+
return new hbs.SafeString(self.compileFile(filePath));
|
|
176
|
+
});
|
|
177
|
+
/**
|
|
178
|
+
* {{#each (tagged "tagname")}} ... {{/each}}
|
|
179
|
+
*
|
|
180
|
+
* Returns an array of objects for iteration. Each object has:
|
|
181
|
+
* - body: recursively compiled content
|
|
182
|
+
* - raw: uncompiled content
|
|
183
|
+
* - path: relative file path
|
|
184
|
+
* - title: frontmatter title (shortcut)
|
|
185
|
+
* - description: frontmatter description (shortcut)
|
|
186
|
+
* - frontmatter: full frontmatter object
|
|
187
|
+
* - instrux: instrux metadata
|
|
188
|
+
*/
|
|
189
|
+
hbs.registerHelper('tagged', function (tagName) {
|
|
190
|
+
self.tagsUsed.add(tagName);
|
|
191
|
+
const files = self.index.tags.get(tagName);
|
|
192
|
+
if (!files || files.length === 0) {
|
|
193
|
+
console.log(` ⚠ Tag "${tagName}" matched 0 files`);
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
const sorted = (0, frontmatter_1.sortSourceFiles)(files);
|
|
197
|
+
return sorted.map(f => ({
|
|
198
|
+
body: self.compileFile(f.path),
|
|
199
|
+
raw: f.content,
|
|
200
|
+
path: f.path,
|
|
201
|
+
title: f.frontmatter.title ?? path.basename(f.path, '.md'),
|
|
202
|
+
description: f.frontmatter.description ?? f.instrux.description ?? '',
|
|
203
|
+
frontmatter: f.frontmatter,
|
|
204
|
+
instrux: f.instrux,
|
|
205
|
+
}));
|
|
206
|
+
});
|
|
207
|
+
/**
|
|
208
|
+
* {{meta "key"}}
|
|
209
|
+
*
|
|
210
|
+
* Access a frontmatter value from the current file's context.
|
|
211
|
+
*/
|
|
212
|
+
hbs.registerHelper('meta', function (key, options) {
|
|
213
|
+
return options.data?.root?.meta?.[key] ?? '';
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
exports.InstruxCompiler = InstruxCompiler;
|
|
218
|
+
//# sourceMappingURL=compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.js","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* instrux - Core engine
|
|
3
|
+
*
|
|
4
|
+
* Loads agent configs, validates source files, and either:
|
|
5
|
+
* - Simple merge: concatenates files in order (v1)
|
|
6
|
+
* - Compile: resolves Handlebars templates + frontmatter tags (v2)
|
|
7
|
+
*/
|
|
8
|
+
import { AgentConfig, BuildResult, ValidationResult } from './types';
|
|
9
|
+
export declare class InstruxEngine {
|
|
10
|
+
private rootDir;
|
|
11
|
+
constructor(rootDir?: string);
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the config path for a given agent name.
|
|
14
|
+
* Looks in `agents/<name>/agent.json`.
|
|
15
|
+
*/
|
|
16
|
+
private agentConfigPath;
|
|
17
|
+
/**
|
|
18
|
+
* Load an agent configuration by name.
|
|
19
|
+
*/
|
|
20
|
+
loadConfig(agentName: string): Promise<AgentConfig>;
|
|
21
|
+
/**
|
|
22
|
+
* List all agents found in the `agents/` directory.
|
|
23
|
+
*/
|
|
24
|
+
listAgents(): Promise<{
|
|
25
|
+
name: string;
|
|
26
|
+
config: AgentConfig | null;
|
|
27
|
+
}[]>;
|
|
28
|
+
validate(config: AgentConfig): Promise<ValidationResult>;
|
|
29
|
+
merge(config: AgentConfig): Promise<string>;
|
|
30
|
+
writeOutput(config: AgentConfig, content: string): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Returns true if the agent config uses the template compiler (v2)
|
|
33
|
+
* instead of simple ordered merge.
|
|
34
|
+
*/
|
|
35
|
+
isCompileMode(config: AgentConfig): boolean;
|
|
36
|
+
build(agentName: string): Promise<BuildResult>;
|
|
37
|
+
contentHash(content: string): string;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EACL,WAAW,EACX,WAAW,EACX,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAGjB,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,CAAC,EAAE,MAAM;IAM5B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBzD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IAgCrE,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAqBxD,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IA+C3C,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BxE;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAIrC,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgDpD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAOrC"}
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* instrux - Core engine
|
|
4
|
+
*
|
|
5
|
+
* Loads agent configs, validates source files, and either:
|
|
6
|
+
* - Simple merge: concatenates files in order (v1)
|
|
7
|
+
* - Compile: resolves Handlebars templates + frontmatter tags (v2)
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.InstruxEngine = void 0;
|
|
44
|
+
const fs = __importStar(require("fs-extra"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const crypto = __importStar(require("crypto"));
|
|
47
|
+
const compiler_1 = require("./compiler");
|
|
48
|
+
class InstruxEngine {
|
|
49
|
+
constructor(rootDir) {
|
|
50
|
+
this.rootDir = rootDir ?? process.cwd();
|
|
51
|
+
}
|
|
52
|
+
// ── Config loading ───────────────────────────────────────
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the config path for a given agent name.
|
|
55
|
+
* Looks in `agents/<name>/agent.json`.
|
|
56
|
+
*/
|
|
57
|
+
agentConfigPath(agentName) {
|
|
58
|
+
return path.join(this.rootDir, 'agents', agentName, 'agent.json');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Load an agent configuration by name.
|
|
62
|
+
*/
|
|
63
|
+
async loadConfig(agentName) {
|
|
64
|
+
const configPath = this.agentConfigPath(agentName);
|
|
65
|
+
if (!(await fs.pathExists(configPath))) {
|
|
66
|
+
throw new Error(`Agent config not found: ${path.relative(this.rootDir, configPath)}\n` +
|
|
67
|
+
`Run "instrux init <name>" to create one.`);
|
|
68
|
+
}
|
|
69
|
+
const raw = await fs.readFile(configPath, 'utf-8');
|
|
70
|
+
return JSON.parse(raw);
|
|
71
|
+
}
|
|
72
|
+
// ── Discovery ────────────────────────────────────────────
|
|
73
|
+
/**
|
|
74
|
+
* List all agents found in the `agents/` directory.
|
|
75
|
+
*/
|
|
76
|
+
async listAgents() {
|
|
77
|
+
const agentsDir = path.join(this.rootDir, 'agents');
|
|
78
|
+
if (!(await fs.pathExists(agentsDir))) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
const entries = await fs.readdir(agentsDir, { withFileTypes: true });
|
|
82
|
+
const dirs = entries.filter(e => e.isDirectory() && e.name !== 'base');
|
|
83
|
+
const agents = [];
|
|
84
|
+
for (const dir of dirs) {
|
|
85
|
+
const configPath = path.join(agentsDir, dir.name, 'agent.json');
|
|
86
|
+
let config = null;
|
|
87
|
+
if (await fs.pathExists(configPath)) {
|
|
88
|
+
try {
|
|
89
|
+
config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// invalid JSON — still list the directory
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
agents.push({ name: dir.name, config });
|
|
96
|
+
}
|
|
97
|
+
return agents;
|
|
98
|
+
}
|
|
99
|
+
// ── Validation ───────────────────────────────────────────
|
|
100
|
+
async validate(config) {
|
|
101
|
+
const missing = [];
|
|
102
|
+
const warnings = [];
|
|
103
|
+
const files = config.files ?? [];
|
|
104
|
+
for (const file of files) {
|
|
105
|
+
const fullPath = path.join(this.rootDir, file.path);
|
|
106
|
+
const exists = await fs.pathExists(fullPath);
|
|
107
|
+
if (!exists && file.required) {
|
|
108
|
+
missing.push(file.path);
|
|
109
|
+
}
|
|
110
|
+
else if (!exists && !file.required) {
|
|
111
|
+
warnings.push(`Optional file not found: ${file.path}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { valid: missing.length === 0, missing, warnings };
|
|
115
|
+
}
|
|
116
|
+
// ── Merge ────────────────────────────────────────────────
|
|
117
|
+
async merge(config) {
|
|
118
|
+
const { mergeSettings } = config;
|
|
119
|
+
let merged = '';
|
|
120
|
+
let first = true;
|
|
121
|
+
const files = config.files ?? [];
|
|
122
|
+
if (mergeSettings.includeFileHeaders) {
|
|
123
|
+
merged += `<!-- Generated by instrux -->\n`;
|
|
124
|
+
merged += `<!-- Agent: ${config.name} -->\n`;
|
|
125
|
+
merged += `<!-- Generated: ${new Date().toISOString()} -->\n\n`;
|
|
126
|
+
}
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
const fullPath = path.join(this.rootDir, file.path);
|
|
129
|
+
let content = '';
|
|
130
|
+
if (await fs.pathExists(fullPath)) {
|
|
131
|
+
content = await fs.readFile(fullPath, 'utf-8');
|
|
132
|
+
}
|
|
133
|
+
if (!content || content.trim().length === 0) {
|
|
134
|
+
const kind = file.required ? 'required' : 'optional';
|
|
135
|
+
console.log(` ⚠ Skipping empty ${kind} file: ${file.path}`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// separator between sections (not before the first)
|
|
139
|
+
if (!first && mergeSettings.addSeparators) {
|
|
140
|
+
merged += `\n${mergeSettings.separatorStyle}\n\n`;
|
|
141
|
+
}
|
|
142
|
+
if (mergeSettings.includeFileHeaders) {
|
|
143
|
+
merged += `<!-- File: ${file.path} -->\n`;
|
|
144
|
+
merged += `<!-- ${file.description} -->\n\n`;
|
|
145
|
+
}
|
|
146
|
+
merged += content;
|
|
147
|
+
if (!content.endsWith('\n'))
|
|
148
|
+
merged += '\n';
|
|
149
|
+
first = false;
|
|
150
|
+
}
|
|
151
|
+
return merged;
|
|
152
|
+
}
|
|
153
|
+
// ── Write output ─────────────────────────────────────────
|
|
154
|
+
async writeOutput(config, content) {
|
|
155
|
+
const outputDir = path.join(this.rootDir, config.outputDirectory);
|
|
156
|
+
await fs.ensureDir(outputDir);
|
|
157
|
+
let fileName = config.outputFilePattern;
|
|
158
|
+
if (config.mergeSettings.useTimestamp) {
|
|
159
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
|
160
|
+
fileName = fileName.replace('{timestamp}', ts);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
fileName = fileName
|
|
164
|
+
.replace('_{timestamp}', '')
|
|
165
|
+
.replace('{timestamp}_', '')
|
|
166
|
+
.replace('{timestamp}', '');
|
|
167
|
+
}
|
|
168
|
+
if (config.mergeSettings.generateHash) {
|
|
169
|
+
const hash = this.contentHash(content);
|
|
170
|
+
fileName = fileName.replace('.md', `_${hash}.md`);
|
|
171
|
+
}
|
|
172
|
+
const outputPath = path.join(outputDir, fileName);
|
|
173
|
+
await fs.writeFile(outputPath, content, 'utf-8');
|
|
174
|
+
return outputPath;
|
|
175
|
+
}
|
|
176
|
+
// ── Build (validate → merge/compile → write) ───────────
|
|
177
|
+
/**
|
|
178
|
+
* Returns true if the agent config uses the template compiler (v2)
|
|
179
|
+
* instead of simple ordered merge.
|
|
180
|
+
*/
|
|
181
|
+
isCompileMode(config) {
|
|
182
|
+
return !!config.entry;
|
|
183
|
+
}
|
|
184
|
+
async build(agentName) {
|
|
185
|
+
const config = await this.loadConfig(agentName);
|
|
186
|
+
// ── Template compilation mode ──────────────────────
|
|
187
|
+
if (this.isCompileMode(config)) {
|
|
188
|
+
const compiler = new compiler_1.InstruxCompiler(this.rootDir, config);
|
|
189
|
+
const result = await compiler.compile();
|
|
190
|
+
const outputPath = await this.writeOutput(config, result.output);
|
|
191
|
+
return {
|
|
192
|
+
outputPath: path.relative(this.rootDir, outputPath),
|
|
193
|
+
contentLength: result.output.length,
|
|
194
|
+
contentHash: this.contentHash(result.output),
|
|
195
|
+
filesIncluded: result.filesCompiled,
|
|
196
|
+
filesSkipped: 0,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
// ── Simple merge mode (v1) ─────────────────────────
|
|
200
|
+
if (!config.files || config.files.length === 0) {
|
|
201
|
+
throw new Error('Agent config must define either "entry" (template mode) or "files" (simple merge mode).');
|
|
202
|
+
}
|
|
203
|
+
const validation = await this.validate(config);
|
|
204
|
+
for (const w of validation.warnings)
|
|
205
|
+
console.log(` ⚠ ${w}`);
|
|
206
|
+
if (!validation.valid) {
|
|
207
|
+
throw new Error(`Missing required files:\n${validation.missing.map(f => ` - ${f}`).join('\n')}`);
|
|
208
|
+
}
|
|
209
|
+
const content = await this.merge(config);
|
|
210
|
+
const outputPath = await this.writeOutput(config, content);
|
|
211
|
+
return {
|
|
212
|
+
outputPath: path.relative(this.rootDir, outputPath),
|
|
213
|
+
contentLength: content.length,
|
|
214
|
+
contentHash: this.contentHash(content),
|
|
215
|
+
filesIncluded: config.files.length,
|
|
216
|
+
filesSkipped: 0,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// ── Helpers ──────────────────────────────────────────────
|
|
220
|
+
contentHash(content) {
|
|
221
|
+
return crypto
|
|
222
|
+
.createHash('md5')
|
|
223
|
+
.update(content)
|
|
224
|
+
.digest('hex')
|
|
225
|
+
.substring(0, 8);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
exports.InstruxEngine = InstruxEngine;
|
|
229
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* instrux — Frontmatter parsing and source file indexing.
|
|
3
|
+
*
|
|
4
|
+
* Scans source directories, parses YAML frontmatter from each markdown file,
|
|
5
|
+
* and builds a tag-based index for the compiler to resolve references.
|
|
6
|
+
*/
|
|
7
|
+
import { SourceFile, SourceIndex } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Scan source file globs, parse frontmatter, and return an indexed collection.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildSourceIndex(rootDir: string, sourcePatterns: string[]): Promise<SourceIndex>;
|
|
12
|
+
/**
|
|
13
|
+
* Sort source files by instrux.order (ascending), then by path.
|
|
14
|
+
*/
|
|
15
|
+
export declare function sortSourceFiles(files: SourceFile[]): SourceFile[];
|
|
16
|
+
/**
|
|
17
|
+
* Strip the instrux block from frontmatter, returning only standard fields.
|
|
18
|
+
* Used when emitting frontmatter in the final output.
|
|
19
|
+
*/
|
|
20
|
+
export declare function stripInstruxMeta(frontmatter: Record<string, any>): Record<string, any>;
|
|
21
|
+
/**
|
|
22
|
+
* Serialize a frontmatter object back to a YAML block (--- delimited).
|
|
23
|
+
* Returns empty string if the object has no keys.
|
|
24
|
+
*/
|
|
25
|
+
export declare function serializeFrontmatter(data: Record<string, any>): string;
|
|
26
|
+
//# sourceMappingURL=frontmatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAE/D;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,WAAW,CAAC,CA2CtB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAOjE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAGrB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAItE"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* instrux — Frontmatter parsing and source file indexing.
|
|
4
|
+
*
|
|
5
|
+
* Scans source directories, parses YAML frontmatter from each markdown file,
|
|
6
|
+
* and builds a tag-based index for the compiler to resolve references.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
42
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.buildSourceIndex = buildSourceIndex;
|
|
46
|
+
exports.sortSourceFiles = sortSourceFiles;
|
|
47
|
+
exports.stripInstruxMeta = stripInstruxMeta;
|
|
48
|
+
exports.serializeFrontmatter = serializeFrontmatter;
|
|
49
|
+
const fs = __importStar(require("fs-extra"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
52
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
53
|
+
/**
|
|
54
|
+
* Scan source file globs, parse frontmatter, and return an indexed collection.
|
|
55
|
+
*/
|
|
56
|
+
async function buildSourceIndex(rootDir, sourcePatterns) {
|
|
57
|
+
// Resolve globs relative to rootDir
|
|
58
|
+
const matched = await (0, fast_glob_1.default)(sourcePatterns, {
|
|
59
|
+
cwd: rootDir,
|
|
60
|
+
onlyFiles: true,
|
|
61
|
+
dot: false,
|
|
62
|
+
ignore: ['**/node_modules/**'],
|
|
63
|
+
});
|
|
64
|
+
const files = [];
|
|
65
|
+
const tags = new Map();
|
|
66
|
+
const paths = new Map();
|
|
67
|
+
for (const relPath of matched) {
|
|
68
|
+
const absPath = path.join(rootDir, relPath);
|
|
69
|
+
const raw = await fs.readFile(absPath, 'utf-8');
|
|
70
|
+
const { data: frontmatter, content } = (0, gray_matter_1.default)(raw);
|
|
71
|
+
const instrux = frontmatter.instrux ?? {};
|
|
72
|
+
const sourceFile = {
|
|
73
|
+
path: relPath.replace(/\\/g, '/'), // normalise to forward slashes
|
|
74
|
+
frontmatter,
|
|
75
|
+
instrux,
|
|
76
|
+
content,
|
|
77
|
+
};
|
|
78
|
+
files.push(sourceFile);
|
|
79
|
+
// normalised path → file
|
|
80
|
+
paths.set(sourceFile.path, sourceFile);
|
|
81
|
+
// build tag index
|
|
82
|
+
if (instrux.tags) {
|
|
83
|
+
for (const tag of instrux.tags) {
|
|
84
|
+
const bucket = tags.get(tag) ?? [];
|
|
85
|
+
bucket.push(sourceFile);
|
|
86
|
+
tags.set(tag, bucket);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { files, tags, paths };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Sort source files by instrux.order (ascending), then by path.
|
|
94
|
+
*/
|
|
95
|
+
function sortSourceFiles(files) {
|
|
96
|
+
return [...files].sort((a, b) => {
|
|
97
|
+
const oa = a.instrux.order ?? 999;
|
|
98
|
+
const ob = b.instrux.order ?? 999;
|
|
99
|
+
if (oa !== ob)
|
|
100
|
+
return oa - ob;
|
|
101
|
+
return a.path.localeCompare(b.path);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Strip the instrux block from frontmatter, returning only standard fields.
|
|
106
|
+
* Used when emitting frontmatter in the final output.
|
|
107
|
+
*/
|
|
108
|
+
function stripInstruxMeta(frontmatter) {
|
|
109
|
+
const { instrux, ...rest } = frontmatter;
|
|
110
|
+
return rest;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Serialize a frontmatter object back to a YAML block (--- delimited).
|
|
114
|
+
* Returns empty string if the object has no keys.
|
|
115
|
+
*/
|
|
116
|
+
function serializeFrontmatter(data) {
|
|
117
|
+
const keys = Object.keys(data);
|
|
118
|
+
if (keys.length === 0)
|
|
119
|
+
return '';
|
|
120
|
+
return gray_matter_1.default.stringify('', data).trimEnd() + '\n\n';
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=frontmatter.js.map
|