@adhd/agent-engine-compiler 2.1.8 → 2.1.10
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/CHANGELOG.md +39 -0
- package/README.md +72 -0
- package/drizzle/meta/_journal.json +5 -0
- package/package.json +9 -31
- package/src/cache/composed-prompt-cache.d.ts +60 -0
- package/src/cache/composed-prompt-cache.d.ts.map +1 -0
- package/src/cache/composed-prompt-cache.js +120 -0
- package/src/cache/composed-prompt-cache.js.map +1 -0
- package/src/cli/compile.d.ts +3 -0
- package/src/cli/compile.d.ts.map +1 -0
- package/src/cli/compile.js +300 -0
- package/src/cli/compile.js.map +1 -0
- package/src/compile.d.ts +61 -0
- package/src/compile.d.ts.map +1 -0
- package/src/compile.js +279 -0
- package/src/compile.js.map +1 -0
- package/src/db/migrate-runner.d.ts +31 -0
- package/src/db/migrate-runner.d.ts.map +1 -0
- package/src/db/migrate-runner.js +35 -0
- package/src/db/migrate-runner.js.map +1 -0
- package/src/db/schema.d.ts +3 -0
- package/src/db/schema.d.ts.map +1 -0
- package/src/db/schema.js +30 -0
- package/src/db/schema.js.map +1 -0
- package/src/emit/json.d.ts +50 -0
- package/src/emit/json.d.ts.map +1 -0
- package/src/emit/json.js +66 -0
- package/src/emit/json.js.map +1 -0
- package/src/emit/markdown.d.ts +35 -0
- package/src/emit/markdown.d.ts.map +1 -0
- package/src/emit/markdown.js +90 -0
- package/src/emit/markdown.js.map +1 -0
- package/src/index.d.ts +18 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +21 -0
- package/src/index.js.map +1 -0
- package/src/resolve/composition.d.ts +28 -0
- package/src/resolve/composition.d.ts.map +1 -0
- package/src/resolve/composition.js +33 -0
- package/src/resolve/composition.js.map +1 -0
- package/src/resolve/model.d.ts +22 -0
- package/src/resolve/model.d.ts.map +1 -0
- package/src/resolve/model.js +69 -0
- package/src/resolve/model.js.map +1 -0
- package/src/resolve/policy.d.ts +34 -0
- package/src/resolve/policy.d.ts.map +1 -0
- package/src/resolve/policy.js +44 -0
- package/src/resolve/policy.js.map +1 -0
- package/src/resolve/tools.d.ts +33 -0
- package/src/resolve/tools.d.ts.map +1 -0
- package/src/resolve/tools.js +62 -0
- package/src/resolve/tools.js.map +1 -0
- package/src/seed/fixtures.d.ts +52 -0
- package/src/seed/fixtures.d.ts.map +1 -0
- package/src/seed/fixtures.js +148 -0
- package/src/seed/fixtures.js.map +1 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ──────────────────────────────────────────────
|
|
3
|
+
// cli/compile.ts — argv parser + dispatcher for the agent-compiler bin.
|
|
4
|
+
//
|
|
5
|
+
// Usage:
|
|
6
|
+
// node cli/compile.js compile <slug> [options]
|
|
7
|
+
//
|
|
8
|
+
// Options:
|
|
9
|
+
// --platform <p> Target platform (default: claude_code).
|
|
10
|
+
// Must match a row in tool_platforms.
|
|
11
|
+
// --context '<json>' Runtime context key/value object (JSON string).
|
|
12
|
+
// --format json Emit JSON instead of platform default.
|
|
13
|
+
// --out-dir <d> Write <slug>.md (or <slug>.json) under <d>
|
|
14
|
+
// instead of printing to stdout.
|
|
15
|
+
// --all Compile every agent in the registry (use with
|
|
16
|
+
// --category to limit scope).
|
|
17
|
+
// --category <c> Filter to agents in this taxonomy category slug.
|
|
18
|
+
// --db <path> Path to the SQLite registry file. Defaults to
|
|
19
|
+
// AGENT_REGISTRY_DB env var, then ~/.agent-registry/registry.db.
|
|
20
|
+
//
|
|
21
|
+
// Exit codes:
|
|
22
|
+
// 0 — success
|
|
23
|
+
// 1 — unknown slug / unknown platform / bad argument / I/O error
|
|
24
|
+
//
|
|
25
|
+
// [ref:cli-bin] — mirrors agent-mcp's bin entry in package.json;
|
|
26
|
+
// parses compile <slug> ... and writes content to stdout or --out-dir.
|
|
27
|
+
// [inv:platform-node] — no browser imports; pure Node + SQLite.
|
|
28
|
+
// [inv:one-db-handle] — opens ONE better-sqlite3 handle for the shared DB.
|
|
29
|
+
// ──────────────────────────────────────────────
|
|
30
|
+
import fs from 'node:fs';
|
|
31
|
+
import path from 'node:path';
|
|
32
|
+
import process from 'node:process';
|
|
33
|
+
import { fileURLToPath } from 'node:url';
|
|
34
|
+
import Database from 'better-sqlite3';
|
|
35
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
36
|
+
import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
|
|
37
|
+
import { resolveRegistryDbPath } from '@adhd/agent-core-env';
|
|
38
|
+
import { AgentStore } from '@adhd/agent-store-prompts';
|
|
39
|
+
import { compileAgent } from '../compile.js';
|
|
40
|
+
// ── Migration folders ─────────────────────────────────────────────────────
|
|
41
|
+
//
|
|
42
|
+
// Resolved relative to this compiled file's __dirname at runtime so the bin
|
|
43
|
+
// works from the dist layout without referencing source paths.
|
|
44
|
+
//
|
|
45
|
+
// dist/packages/agent/agent-engine-compiler/src/cli/compile.js
|
|
46
|
+
// → ../../ = dist/packages/agent/agent-engine-compiler/
|
|
47
|
+
// → ../../../ = dist/packages/agent/
|
|
48
|
+
// → ../../../<pkg>/drizzle = dist/packages/agent/<pkg>/drizzle
|
|
49
|
+
//
|
|
50
|
+
// Timestamp order (ascending) matters so Drizzle's journal bookkeeping
|
|
51
|
+
// doesn't skip a migration set:
|
|
52
|
+
// provider (1750*) → registry (1782193*) → tool-registry (1782250*)
|
|
53
|
+
// → policy (1782256*) → compiler (18*)
|
|
54
|
+
//
|
|
55
|
+
// This mirrors the migration order in compile-agent.test.ts.
|
|
56
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
57
|
+
const AI_DIST = path.resolve(__dirname, '../../../');
|
|
58
|
+
const PROVIDER_MIGRATIONS = path.join(AI_DIST, 'agent-core-provider/drizzle');
|
|
59
|
+
const REGISTRY_MIGRATIONS = path.join(AI_DIST, 'agent-store-prompts/drizzle');
|
|
60
|
+
const TOOL_REGISTRY_MIGRATIONS = path.join(AI_DIST, 'agent-store-tools/drizzle');
|
|
61
|
+
const POLICY_MIGRATIONS = path.join(AI_DIST, 'agent-core-policy/drizzle');
|
|
62
|
+
const COMPILER_MIGRATIONS = path.join(AI_DIST, 'agent-engine-compiler/drizzle');
|
|
63
|
+
// ──────────────────────────────────────────────
|
|
64
|
+
// argv parser
|
|
65
|
+
// ──────────────────────────────────────────────
|
|
66
|
+
/**
|
|
67
|
+
* Parse process.argv into a CliArgs object.
|
|
68
|
+
* Exits 1 with a usage message on any parse error.
|
|
69
|
+
*/
|
|
70
|
+
function parseArgs(argv) {
|
|
71
|
+
// argv: [ node, compile.js, 'compile', <slug?>, ...flags ]
|
|
72
|
+
const args = argv.slice(2); // strip node + script path
|
|
73
|
+
if (args[0] !== 'compile') {
|
|
74
|
+
die(`Expected sub-command 'compile', got: ${args[0] ?? '(nothing)'}`);
|
|
75
|
+
}
|
|
76
|
+
let slug = null;
|
|
77
|
+
let platform = 'claude_code';
|
|
78
|
+
let context = {};
|
|
79
|
+
let formatJson = false;
|
|
80
|
+
let outDir = null;
|
|
81
|
+
let all = false;
|
|
82
|
+
let category = null;
|
|
83
|
+
// AGENT_REGISTRY_DB is this CLI's own pre-existing, bin-specific legacy
|
|
84
|
+
// override (kept for back-compat) — it wins over the shared resolver's
|
|
85
|
+
// canonical default but not over an explicit --db flag (applied below).
|
|
86
|
+
// resolveRegistryDbPath() itself still checks the 3 documented
|
|
87
|
+
// registry-family env vars (ADHD_AGENT_REGISTRY_DB_PATH,
|
|
88
|
+
// REGISTRY_DATABASE_PATH, DATABASE_PATH) before falling back to the
|
|
89
|
+
// @adhd/environment-resolved canonical default.
|
|
90
|
+
let dbPath = process.env['AGENT_REGISTRY_DB'] ?? resolveRegistryDbPath();
|
|
91
|
+
const flags = args.slice(1); // everything after 'compile'
|
|
92
|
+
let i = 0;
|
|
93
|
+
while (i < flags.length) {
|
|
94
|
+
const tok = flags[i];
|
|
95
|
+
if (tok === '--platform') {
|
|
96
|
+
platform = requireNext(flags, i, '--platform');
|
|
97
|
+
i += 2;
|
|
98
|
+
}
|
|
99
|
+
else if (tok === '--context') {
|
|
100
|
+
const raw = requireNext(flags, i, '--context');
|
|
101
|
+
try {
|
|
102
|
+
// Parse as unknown first, then cast to CompositionContext (Record<string, string>).
|
|
103
|
+
// The runtime contract is that --context values are string-keyed, string-valued.
|
|
104
|
+
context = JSON.parse(raw);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
die(`--context must be valid JSON; got: ${raw}`);
|
|
108
|
+
}
|
|
109
|
+
i += 2;
|
|
110
|
+
}
|
|
111
|
+
else if (tok === '--format') {
|
|
112
|
+
const fmt = requireNext(flags, i, '--format');
|
|
113
|
+
if (fmt !== 'json') {
|
|
114
|
+
die(`--format only supports 'json'; got: '${fmt}'`);
|
|
115
|
+
}
|
|
116
|
+
formatJson = true;
|
|
117
|
+
i += 2;
|
|
118
|
+
}
|
|
119
|
+
else if (tok === '--out-dir') {
|
|
120
|
+
outDir = requireNext(flags, i, '--out-dir');
|
|
121
|
+
i += 2;
|
|
122
|
+
}
|
|
123
|
+
else if (tok === '--all') {
|
|
124
|
+
all = true;
|
|
125
|
+
i++;
|
|
126
|
+
}
|
|
127
|
+
else if (tok === '--category') {
|
|
128
|
+
category = requireNext(flags, i, '--category');
|
|
129
|
+
i += 2;
|
|
130
|
+
}
|
|
131
|
+
else if (tok === '--db') {
|
|
132
|
+
dbPath = requireNext(flags, i, '--db');
|
|
133
|
+
i += 2;
|
|
134
|
+
}
|
|
135
|
+
else if (tok != null && !tok.startsWith('-')) {
|
|
136
|
+
// Positional slug — only accepted once.
|
|
137
|
+
if (slug !== null) {
|
|
138
|
+
die(`Unexpected extra positional argument: '${tok}'`);
|
|
139
|
+
}
|
|
140
|
+
slug = tok;
|
|
141
|
+
i++;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
die(`Unknown flag: '${tok}'`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (!all && slug === null) {
|
|
148
|
+
die('Provide a slug (compile <slug>) or use --all [--category <c>]');
|
|
149
|
+
}
|
|
150
|
+
if (all && slug !== null) {
|
|
151
|
+
die('--all and a positional slug are mutually exclusive');
|
|
152
|
+
}
|
|
153
|
+
return { slug, platform, context, formatJson, outDir, all, category, dbPath };
|
|
154
|
+
}
|
|
155
|
+
function requireNext(flags, i, flag) {
|
|
156
|
+
const val = flags[i + 1];
|
|
157
|
+
if (val == null || val.startsWith('-')) {
|
|
158
|
+
die(`${flag} requires a value`);
|
|
159
|
+
}
|
|
160
|
+
return val;
|
|
161
|
+
}
|
|
162
|
+
// ──────────────────────────────────────────────
|
|
163
|
+
// DB open helper
|
|
164
|
+
// ──────────────────────────────────────────────
|
|
165
|
+
/**
|
|
166
|
+
* Open the shared SQLite registry file and apply migrations so the schema is
|
|
167
|
+
* always current ([inv:one-db-handle]).
|
|
168
|
+
*
|
|
169
|
+
* Runs all five migration sets in ascending timestamp order so Drizzle's
|
|
170
|
+
* journal does not skip any set.
|
|
171
|
+
*/
|
|
172
|
+
function openDb(dbPath) {
|
|
173
|
+
if (!fs.existsSync(dbPath)) {
|
|
174
|
+
const parent = path.dirname(dbPath);
|
|
175
|
+
if (!fs.existsSync(parent)) {
|
|
176
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const conn = new Database(dbPath);
|
|
180
|
+
conn.pragma('journal_mode = WAL');
|
|
181
|
+
conn.pragma('foreign_keys = OFF');
|
|
182
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
183
|
+
const db = drizzle(conn, { schema: {} });
|
|
184
|
+
// Migrate in ascending timestamp order — same pattern as the test suite.
|
|
185
|
+
for (const folder of [
|
|
186
|
+
PROVIDER_MIGRATIONS,
|
|
187
|
+
REGISTRY_MIGRATIONS,
|
|
188
|
+
TOOL_REGISTRY_MIGRATIONS,
|
|
189
|
+
POLICY_MIGRATIONS,
|
|
190
|
+
COMPILER_MIGRATIONS,
|
|
191
|
+
]) {
|
|
192
|
+
if (fs.existsSync(folder)) {
|
|
193
|
+
migrate(db, { migrationsFolder: folder });
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
process.stderr.write(`agent-compiler: warning: migration folder not found: ${folder}\n`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
conn.pragma('foreign_keys = ON');
|
|
200
|
+
return { conn, db };
|
|
201
|
+
}
|
|
202
|
+
// ──────────────────────────────────────────────
|
|
203
|
+
// Compile a single agent → string artifact
|
|
204
|
+
// ──────────────────────────────────────────────
|
|
205
|
+
function compileSingle(slug, args,
|
|
206
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
207
|
+
db) {
|
|
208
|
+
let result;
|
|
209
|
+
try {
|
|
210
|
+
result = compileAgent({
|
|
211
|
+
agentSlug: slug,
|
|
212
|
+
platform: args.platform,
|
|
213
|
+
context: args.context,
|
|
214
|
+
db,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
219
|
+
// Distinguish AGENT_NOT_FOUND / PLATFORM_NOT_FOUND from other errors.
|
|
220
|
+
if (msg.includes('not found') || msg.includes('NOT_FOUND')) {
|
|
221
|
+
die(`Error: ${msg}`);
|
|
222
|
+
}
|
|
223
|
+
die(`Compilation failed for '${slug}' on platform '${args.platform}': ${msg}`);
|
|
224
|
+
}
|
|
225
|
+
// --format json overrides the platform's default header format.
|
|
226
|
+
if (args.formatJson) {
|
|
227
|
+
// If content is already JSON (json_object platforms), return as-is.
|
|
228
|
+
try {
|
|
229
|
+
JSON.parse(result.content);
|
|
230
|
+
return result.content; // already valid JSON
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Wrap markdown in a JSON envelope.
|
|
234
|
+
return JSON.stringify({
|
|
235
|
+
systemPrompt: result.content,
|
|
236
|
+
tools: result.tools,
|
|
237
|
+
componentVersions: result.componentVersions,
|
|
238
|
+
}, null, 2);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return result.content;
|
|
242
|
+
}
|
|
243
|
+
// ──────────────────────────────────────────────
|
|
244
|
+
// Output helper
|
|
245
|
+
// ──────────────────────────────────────────────
|
|
246
|
+
/**
|
|
247
|
+
* Write content either to stdout or to <outDir>/<slug>.<ext>.
|
|
248
|
+
*/
|
|
249
|
+
function writeOutput(slug, content, args) {
|
|
250
|
+
if (args.outDir === null) {
|
|
251
|
+
process.stdout.write(content);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
fs.mkdirSync(args.outDir, { recursive: true });
|
|
255
|
+
const ext = args.formatJson ? 'json' : 'md';
|
|
256
|
+
const dest = path.join(args.outDir, `${slug}.${ext}`);
|
|
257
|
+
fs.writeFileSync(dest, content, 'utf8');
|
|
258
|
+
}
|
|
259
|
+
// ──────────────────────────────────────────────
|
|
260
|
+
// Fatal error helper
|
|
261
|
+
// ──────────────────────────────────────────────
|
|
262
|
+
function die(msg) {
|
|
263
|
+
process.stderr.write(`agent-compiler: ${msg}\n`);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
// ──────────────────────────────────────────────
|
|
267
|
+
// Main
|
|
268
|
+
// ──────────────────────────────────────────────
|
|
269
|
+
function main() {
|
|
270
|
+
const args = parseArgs(process.argv);
|
|
271
|
+
const { conn, db } = openDb(args.dbPath);
|
|
272
|
+
try {
|
|
273
|
+
if (args.all) {
|
|
274
|
+
// Compile every agent in the registry, optionally filtered by category.
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
276
|
+
const agentStore = new AgentStore(db);
|
|
277
|
+
const agents = agentStore.list(args.category ? { category: args.category } : {});
|
|
278
|
+
if (agents.length === 0) {
|
|
279
|
+
const scope = args.category ? ` in category '${args.category}'` : '';
|
|
280
|
+
process.stderr.write(`agent-compiler: no agents found${scope}\n`);
|
|
281
|
+
// Exit 0 — empty category is not an error.
|
|
282
|
+
}
|
|
283
|
+
for (const agent of agents) {
|
|
284
|
+
const content = compileSingle(agent.slug, args, db);
|
|
285
|
+
writeOutput(agent.slug, content, args);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Single-slug path.
|
|
290
|
+
// slug is guaranteed non-null here by parseArgs.
|
|
291
|
+
const content = compileSingle(args.slug, args, db);
|
|
292
|
+
writeOutput(args.slug, content, args);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
conn.close();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
main();
|
|
300
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../../src/cli/compile.ts"],"names":[],"mappings":";AACA,iDAAiD;AACjD,wEAAwE;AACxE,EAAE;AACF,SAAS;AACT,iDAAiD;AACjD,EAAE;AACF,WAAW;AACX,gEAAgE;AAChE,4DAA4D;AAC5D,wEAAwE;AACxE,+DAA+D;AAC/D,mEAAmE;AACnE,uDAAuD;AACvD,sEAAsE;AACtE,oDAAoD;AACpD,yEAAyE;AACzE,sEAAsE;AACtE,uFAAuF;AACvF,EAAE;AACF,cAAc;AACd,iBAAiB;AACjB,oEAAoE;AACpE,EAAE;AACF,iEAAiE;AACjE,yEAAyE;AACzE,gEAAgE;AAChE,2EAA2E;AAC3E,iDAAiD;AAEjD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AAG9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,6EAA6E;AAC7E,EAAE;AACF,4EAA4E;AAC5E,+DAA+D;AAC/D,EAAE;AACF,+DAA+D;AAC/D,wEAAwE;AACxE,kDAAkD;AAClD,iEAAiE;AACjE,EAAE;AACF,uEAAuE;AACvE,gCAAgC;AAChC,0EAA0E;AAC1E,8CAA8C;AAC9C,EAAE;AACF,6DAA6D;AAE7D,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;AAErD,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;AAC9E,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;AAC9E,MAAM,wBAAwB,GAAG,IAAI,CAAC,IAAI,CACxC,OAAO,EACP,2BAA2B,CAC5B,CAAC;AACF,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;AAC1E,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,+BAA+B,CAAC,CAAC;AAiBhF,iDAAiD;AACjD,cAAc;AACd,iDAAiD;AAEjD;;;GAGG;AACH,SAAS,SAAS,CAAC,IAAc;IAC/B,2DAA2D;IAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B;IAEvD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC1B,GAAG,CAAC,wCAAwC,IAAI,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,QAAQ,GAAG,aAAa,CAAC;IAC7B,IAAI,OAAO,GAAuB,EAAE,CAAC;IACrC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,wEAAwE;IACxE,uEAAuE;IACvE,wEAAwE;IACxE,+DAA+D;IAC/D,yDAAyD;IACzD,oEAAoE;IACpE,gDAAgD;IAChD,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,qBAAqB,EAAE,CAAC;IAEzE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,6BAA6B;IAC1D,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAErB,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;YAC/C,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;YAC/C,IAAI,CAAC;gBACH,oFAAoF;gBACpF,iFAAiF;gBACjF,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,sCAAsC,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YAC9C,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,GAAG,CAAC,wCAAwC,GAAG,GAAG,CAAC,CAAC;YACtD,CAAC;YACD,UAAU,GAAG,IAAI,CAAC;YAClB,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAC/B,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;YAC5C,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YAC3B,GAAG,GAAG,IAAI,CAAC;YACX,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YAChC,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;YAC/C,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YAC1B,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,wCAAwC;YACxC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,GAAG,CAAC,0CAA0C,GAAG,GAAG,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,GAAG,GAAG,CAAC;YACX,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,kBAAkB,GAAG,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC1B,GAAG,CAAC,+DAA+D,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QACzB,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AAChF,CAAC;AAED,SAAS,WAAW,CAAC,KAAe,EAAE,CAAS,EAAE,IAAY;IAC3D,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,GAAG,IAAI,mBAAmB,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,iBAAiB;AACjB,iDAAiD;AAEjD;;;;;;GAMG;AACH,SAAS,MAAM,CAAC,MAAc;IAK5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAClC,8DAA8D;IAC9D,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAS,EAAE,CAAC,CAAC;IAEhD,yEAAyE;IACzE,KAAK,MAAM,MAAM,IAAI;QACnB,mBAAmB;QACnB,mBAAmB;QACnB,wBAAwB;QACxB,iBAAiB;QACjB,mBAAmB;KACpB,EAAE,CAAC;QACF,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wDAAwD,MAAM,IAAI,CACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACjC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACtB,CAAC;AAED,iDAAiD;AACjD,2CAA2C;AAC3C,iDAAiD;AAEjD,SAAS,aAAa,CACpB,IAAY,EACZ,IAAa;AACb,8DAA8D;AAC9D,EAA8B;IAE9B,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC;YACpB,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,EAAE;SACH,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,sEAAsE;QACtE,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CACD,2BAA2B,IAAI,kBAAkB,IAAI,CAAC,QAAQ,MAAM,GAAG,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,oEAAoE;QACpE,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;YACpC,OAAO,IAAI,CAAC,SAAS,CACnB;gBACE,YAAY,EAAE,MAAM,CAAC,OAAO;gBAC5B,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;aAC5C,EACD,IAAI,EACJ,CAAC,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED,iDAAiD;AACjD,gBAAgB;AAChB,iDAAiD;AAEjD;;GAEG;AACH,SAAS,WAAW,CAAC,IAAY,EAAE,OAAe,EAAE,IAAa;IAC/D,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;IACtD,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,iDAAiD;AACjD,qBAAqB;AACrB,iDAAiD;AAEjD,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,iDAAiD;AACjD,OAAO;AACP,iDAAiD;AAEjD,SAAS,IAAI;IACX,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEzC,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,wEAAwE;YACxE,8DAA8D;YAC9D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,EAAS,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAC5B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CACjD,CAAC;YAEF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,KAAK,IAAI,CAAC,CAAC;gBAClE,2CAA2C;YAC7C,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBACpD,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,oBAAoB;YACpB,iDAAiD;YACjD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,IAAc,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7D,WAAW,CAAC,IAAI,CAAC,IAAc,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/src/compile.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
2
|
+
import type { CompositionContext } from '@adhd/agent-store-prompts';
|
|
3
|
+
import type { ComponentVersionMap } from './resolve/composition.js';
|
|
4
|
+
import type { StructuredTool } from './emit/json.js';
|
|
5
|
+
/** Input to compileAgent ([def:compile-input]). */
|
|
6
|
+
export interface CompileInput {
|
|
7
|
+
/** Slug of the agent to compile. */
|
|
8
|
+
agentSlug: string;
|
|
9
|
+
/** Target platform id (e.g. 'claude_code', 'claude_api'). */
|
|
10
|
+
platform: string;
|
|
11
|
+
/** Runtime context key/value map for context-conditioned components. */
|
|
12
|
+
context?: CompositionContext;
|
|
13
|
+
/** Shared registry Drizzle handle (all four table prefixes — [inv:one-db-handle]). */
|
|
14
|
+
db: BetterSQLite3Database<any>;
|
|
15
|
+
}
|
|
16
|
+
/** Return value of compileAgent ([def:composed-output]). */
|
|
17
|
+
export interface CompiledAgent {
|
|
18
|
+
/**
|
|
19
|
+
* `composed_prompts` row id (audit/cache handle).
|
|
20
|
+
* The inserted `registry_composed_prompts` row id (on MISS, written by the
|
|
21
|
+
* cache layer) or the existing row id (on HIT, served from the cache).
|
|
22
|
+
* Wired by the composed-prompt-caching state ([def:composed-output]).
|
|
23
|
+
*/
|
|
24
|
+
id: number;
|
|
25
|
+
/** Flat platform artifact (markdown for claude_code, JSON string for claude_api/openai). */
|
|
26
|
+
content: string;
|
|
27
|
+
/**
|
|
28
|
+
* Resolved platform-shaped tools.
|
|
29
|
+
* For claude_code: string[] of aliases (e.g. ['Read','Grep','WebSearch']).
|
|
30
|
+
* For claude_api: StructuredTool[] (EmittedTool[]) shaped for the API.
|
|
31
|
+
* For none-format: [] (platform does not support tool selection).
|
|
32
|
+
*/
|
|
33
|
+
tools: string[] | StructuredTool[];
|
|
34
|
+
/**
|
|
35
|
+
* Map of componentSlug → resolvedVersion for cache-key computation
|
|
36
|
+
* ([def:context-hash]).
|
|
37
|
+
*/
|
|
38
|
+
componentVersions: ComponentVersionMap;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Compile an agent to a flat, platform-shaped artifact.
|
|
42
|
+
*
|
|
43
|
+
* Orchestrates the four resolve layers:
|
|
44
|
+
* 1. body + componentVersions — CompositionStore.resolveComposition (junction order)
|
|
45
|
+
* 2. tools — resolveTools (platform aliases)
|
|
46
|
+
* 3. model — resolveModel (platform binding or canonical fallback)
|
|
47
|
+
* 4. constraints — resolvePolicyConstraints (direct + inherited)
|
|
48
|
+
*
|
|
49
|
+
* Then dispatches on the platform's `header_format` column to the matching
|
|
50
|
+
* emit function. The `id` field is null until `composed-prompt-caching`
|
|
51
|
+
* wires the cache write ([def:composed-output]).
|
|
52
|
+
*
|
|
53
|
+
* @param input - Agent slug, target platform, runtime context, shared DB handle.
|
|
54
|
+
* @returns Compiled platform artifact plus metadata.
|
|
55
|
+
*
|
|
56
|
+
* @throws {AgentError} AGENT_NOT_FOUND — agentSlug not in registry_agents.
|
|
57
|
+
* @throws {CompositionError} REQUIRED_COMPONENT_EXCLUDED — a required component
|
|
58
|
+
* was excluded by the runtime context.
|
|
59
|
+
*/
|
|
60
|
+
export declare function compileAgent(input: CompileInput): CompiledAgent;
|
|
61
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAUpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAUrD,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,sFAAsF;IAEtF,EAAE,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAC;CAChC;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IACnC;;;OAGG;IACH,iBAAiB,EAAE,mBAAmB,CAAC;CACxC;AA6DD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,CA6N/D"}
|
package/src/compile.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
// ──────────────────────────────────────────────
|
|
2
|
+
// compileAgent — public orchestrator.
|
|
3
|
+
//
|
|
4
|
+
// Turns an agent definition + runtime context into a flat, platform-shaped
|
|
5
|
+
// artifact by composing the four resolve layers and dispatching to the
|
|
6
|
+
// platform's header builder.
|
|
7
|
+
//
|
|
8
|
+
// Decision B (decisions.md) defines three header builders keyed on a
|
|
9
|
+
// platform's `header_format` column:
|
|
10
|
+
//
|
|
11
|
+
// yaml_frontmatter → emit/markdown.ts (claude_code)
|
|
12
|
+
// json_object → emit/json.ts (claude_api / openai / bedrock)
|
|
13
|
+
// none → body text only (cursor / vscode)
|
|
14
|
+
//
|
|
15
|
+
// The builder is selected by DATA (header_format), never by a hard-coded
|
|
16
|
+
// platform name check. Adding a platform that shares an existing
|
|
17
|
+
// header_format requires no code change here.
|
|
18
|
+
//
|
|
19
|
+
// \n\n section separator advisory (carry-forward, decisions.md Decision B.1):
|
|
20
|
+
// resolve/composition.ts:72 joins body sections with a single '\n'.
|
|
21
|
+
// composition.ts is read-only. To produce the '\n\n'-separated body
|
|
22
|
+
// mandated by Decision B.1, this function calls CompositionStore.resolveComposition
|
|
23
|
+
// directly and owns the join, bypassing resolveBody's pre-joined string.
|
|
24
|
+
// This is the emit-layer fix authorised by the advisory — no composition.ts
|
|
25
|
+
// edit required.
|
|
26
|
+
//
|
|
27
|
+
// [def:compile-input] — {agentSlug, platform, context, db}
|
|
28
|
+
// [def:composed-output] — {id, content, tools, componentVersions}
|
|
29
|
+
// [inv:one-db-handle] — ONE shared SQLite handle, all four table prefixes.
|
|
30
|
+
// [inv:real-rows-not-mocks] — the caller seeds real rows; this function
|
|
31
|
+
// reads them through the upstream stores.
|
|
32
|
+
// ──────────────────────────────────────────────
|
|
33
|
+
import { AgentStore, CompositionStore } from '@adhd/agent-store-prompts';
|
|
34
|
+
import { ToolStore, BindingStore } from '@adhd/agent-store-tools';
|
|
35
|
+
import { ToolFormatStore, emitToolsForProvider } from '@adhd/agent-core-provider';
|
|
36
|
+
import { resolveTools } from './resolve/tools.js';
|
|
37
|
+
import { resolveModel } from './resolve/model.js';
|
|
38
|
+
import { resolvePolicyConstraints } from './resolve/policy.js';
|
|
39
|
+
import { emitYamlFrontmatter } from './emit/markdown.js';
|
|
40
|
+
import { emitJsonObject } from './emit/json.js';
|
|
41
|
+
import { lookup as cacheL, write as cacheW, } from './cache/composed-prompt-cache.js';
|
|
42
|
+
// ──────────────────────────────────────────────
|
|
43
|
+
// Internal helpers
|
|
44
|
+
// ──────────────────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* Look up the `header_format` for a platform from `tool_platform_bindings.platforms`.
|
|
47
|
+
* Returns the platform's `headerFormat` column, or 'none' if no row is found.
|
|
48
|
+
*/
|
|
49
|
+
function getPlatformHeaderFormat(
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
db, platform) {
|
|
52
|
+
const bindingStore = new BindingStore(db);
|
|
53
|
+
// BindingStore.readPlatform throws PLATFORM_NOT_FOUND when absent — treat
|
|
54
|
+
// an unknown platform as 'none' (body-only compile).
|
|
55
|
+
try {
|
|
56
|
+
const p = bindingStore.readPlatform(platform);
|
|
57
|
+
return p.headerFormat;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Unknown platform — treat as 'none' (body-only).
|
|
61
|
+
return 'none';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Extract body sections (in junction order) and componentVersions directly from
|
|
66
|
+
* CompositionStore — bypassing resolveBody's '\n'-joined string so we can
|
|
67
|
+
* join sections with '\n\n' as Decision B.1 mandates.
|
|
68
|
+
*
|
|
69
|
+
* This is the emit-layer fix for the advisory noted in decisions.md.
|
|
70
|
+
*/
|
|
71
|
+
function extractBodyParts(
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
db, agentSlug, context) {
|
|
74
|
+
const store = new CompositionStore(
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
|
+
db);
|
|
77
|
+
const resolved = store.resolveComposition(agentSlug, context);
|
|
78
|
+
const componentVersions = {};
|
|
79
|
+
const bodySections = [];
|
|
80
|
+
for (const rc of resolved) {
|
|
81
|
+
bodySections.push(rc.component.content);
|
|
82
|
+
componentVersions[rc.componentSlug] = rc.resolvedVersion;
|
|
83
|
+
}
|
|
84
|
+
return { bodySections, componentVersions };
|
|
85
|
+
}
|
|
86
|
+
// ──────────────────────────────────────────────
|
|
87
|
+
// Public API
|
|
88
|
+
// ──────────────────────────────────────────────
|
|
89
|
+
/**
|
|
90
|
+
* Compile an agent to a flat, platform-shaped artifact.
|
|
91
|
+
*
|
|
92
|
+
* Orchestrates the four resolve layers:
|
|
93
|
+
* 1. body + componentVersions — CompositionStore.resolveComposition (junction order)
|
|
94
|
+
* 2. tools — resolveTools (platform aliases)
|
|
95
|
+
* 3. model — resolveModel (platform binding or canonical fallback)
|
|
96
|
+
* 4. constraints — resolvePolicyConstraints (direct + inherited)
|
|
97
|
+
*
|
|
98
|
+
* Then dispatches on the platform's `header_format` column to the matching
|
|
99
|
+
* emit function. The `id` field is null until `composed-prompt-caching`
|
|
100
|
+
* wires the cache write ([def:composed-output]).
|
|
101
|
+
*
|
|
102
|
+
* @param input - Agent slug, target platform, runtime context, shared DB handle.
|
|
103
|
+
* @returns Compiled platform artifact plus metadata.
|
|
104
|
+
*
|
|
105
|
+
* @throws {AgentError} AGENT_NOT_FOUND — agentSlug not in registry_agents.
|
|
106
|
+
* @throws {CompositionError} REQUIRED_COMPONENT_EXCLUDED — a required component
|
|
107
|
+
* was excluded by the runtime context.
|
|
108
|
+
*/
|
|
109
|
+
export function compileAgent(input) {
|
|
110
|
+
const { agentSlug, platform, context = {}, db } = input;
|
|
111
|
+
// ── 1. Agent metadata (description for frontmatter, model_hint for model step) ──
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
113
|
+
const agentStore = new AgentStore(db);
|
|
114
|
+
const agent = agentStore.read(agentSlug);
|
|
115
|
+
// ── 2. Determine header_format from the platform row ────────────────────
|
|
116
|
+
const headerFormat = getPlatformHeaderFormat(db, platform);
|
|
117
|
+
// ── 3. Body sections in junction order with '\n\n' separator ────────────
|
|
118
|
+
// Direct call to CompositionStore — bypasses resolveBody's '\n' join so
|
|
119
|
+
// we can apply Decision B.1's '\n\n' between sections at the emit layer.
|
|
120
|
+
// NOTE: extractBodyParts is a cheap read; we run it before the cache check
|
|
121
|
+
// so we have `componentVersions` to fold into the combined context_hash
|
|
122
|
+
// (Decision D: the hash covers BOTH context AND resolved version set).
|
|
123
|
+
const { bodySections, componentVersions } = extractBodyParts(db, agentSlug, context);
|
|
124
|
+
// ── 3b. Cache lookup (BEFORE assembly — [dod.4] negative-control) ────────
|
|
125
|
+
// Decision D: lookup by (agentSlug, platform, context, componentVersions).
|
|
126
|
+
// On HIT: return the persisted {id, content} WITHOUT re-running the resolve
|
|
127
|
+
// layers (steps 4-7 are bypassed). Removing this SELECT causes a duplicate
|
|
128
|
+
// row on every compile — that is the [dod.4] negative-control.
|
|
129
|
+
const hit = cacheL(db, agentSlug, platform, context, componentVersions);
|
|
130
|
+
if (hit !== null) {
|
|
131
|
+
// Cache HIT: serve the persisted artifact. `tools` and `componentVersions`
|
|
132
|
+
// are reconstructed from the already-resolved data (they are cheap reads
|
|
133
|
+
// and do not require re-running the full assembly).
|
|
134
|
+
const resolvedToolsForHit = resolveTools(db, agentSlug, platform);
|
|
135
|
+
if (headerFormat === 'yaml_frontmatter') {
|
|
136
|
+
return {
|
|
137
|
+
id: hit.id,
|
|
138
|
+
content: hit.content,
|
|
139
|
+
tools: resolvedToolsForHit.map((t) => t.platformAlias),
|
|
140
|
+
componentVersions: hit.componentVersions,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (headerFormat === 'json_object') {
|
|
144
|
+
// For JSON platforms, tools is a structured array; reconstruct from the
|
|
145
|
+
// same resolve path so the return shape is consistent.
|
|
146
|
+
const toolStore = new ToolStore(db);
|
|
147
|
+
const toolFormatStore = new ToolFormatStore(db);
|
|
148
|
+
const lookupFmt = (pid, ct) => toolFormatStore.getShape(pid, ct);
|
|
149
|
+
const platformToProvider = {
|
|
150
|
+
claude_api: 'anthropic',
|
|
151
|
+
openai: 'openai',
|
|
152
|
+
bedrock: 'bedrock',
|
|
153
|
+
};
|
|
154
|
+
const providerId = platformToProvider[platform] ?? platform;
|
|
155
|
+
const toolDefs = resolvedToolsForHit.map((rt) => {
|
|
156
|
+
let description = '';
|
|
157
|
+
try {
|
|
158
|
+
description = toolStore.read(rt.canonicalName).description;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
description = rt.canonicalName;
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
name: rt.canonicalName,
|
|
165
|
+
description,
|
|
166
|
+
inputSchema: {},
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
const emittedTools = emitToolsForProvider(toolDefs, providerId, lookupFmt);
|
|
170
|
+
return {
|
|
171
|
+
id: hit.id,
|
|
172
|
+
content: hit.content,
|
|
173
|
+
tools: emittedTools,
|
|
174
|
+
componentVersions: hit.componentVersions,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// none format — no tools
|
|
178
|
+
return {
|
|
179
|
+
id: hit.id,
|
|
180
|
+
content: hit.content,
|
|
181
|
+
tools: [],
|
|
182
|
+
componentVersions: hit.componentVersions,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// ── 4. Resolve tools (platform aliases) ─────────────────────────────────
|
|
186
|
+
const resolvedTools = resolveTools(db, agentSlug, platform);
|
|
187
|
+
// ── 5. Resolve model ─────────────────────────────────────────────────────
|
|
188
|
+
const model = resolveModel(db, agentSlug, platform);
|
|
189
|
+
// ── 6. Resolve policy constraints ────────────────────────────────────────
|
|
190
|
+
const constraints = resolvePolicyConstraints(db, agentSlug);
|
|
191
|
+
// ── 7. Dispatch on header_format ─────────────────────────────────────────
|
|
192
|
+
// yaml_frontmatter (claude_code) ──────────────────────────────────────────
|
|
193
|
+
if (headerFormat === 'yaml_frontmatter') {
|
|
194
|
+
const content = emitYamlFrontmatter({
|
|
195
|
+
agentSlug,
|
|
196
|
+
description: agent.description,
|
|
197
|
+
tools: resolvedTools,
|
|
198
|
+
model,
|
|
199
|
+
bodySections,
|
|
200
|
+
constraints,
|
|
201
|
+
});
|
|
202
|
+
// Tools return: string[] of platform aliases for claude_code.
|
|
203
|
+
const toolAliases = resolvedTools.map((t) => t.platformAlias);
|
|
204
|
+
// ── 7a. Cache WRITE (MISS path) ────────────────────────────────────────
|
|
205
|
+
const written = cacheW(db, agentSlug, platform, context, componentVersions, content);
|
|
206
|
+
return { id: written.id, content, tools: toolAliases, componentVersions };
|
|
207
|
+
}
|
|
208
|
+
// json_object (claude_api / openai / bedrock) ─────────────────────────────
|
|
209
|
+
if (headerFormat === 'json_object') {
|
|
210
|
+
// Build structured tool array for the API.
|
|
211
|
+
// We construct minimal ToolDefinition objects from the tool catalog so
|
|
212
|
+
// emitToolsForProvider can shape them. inputSchema defaults to {} since
|
|
213
|
+
// the registry doesn't store JSON schemas for tool grants.
|
|
214
|
+
const toolStore = new ToolStore(db);
|
|
215
|
+
const toolFormatStore = new ToolFormatStore(db);
|
|
216
|
+
const lookupFmt = (providerId, canonicalTool) => toolFormatStore.getShape(providerId, canonicalTool);
|
|
217
|
+
// Map the target platform id to the provider id (Decision B.2: tools shaped
|
|
218
|
+
// via provider_tool_formats). claude_api → 'anthropic' is the seed mapping
|
|
219
|
+
// from SEED_DATA.md §5; openai → 'openai'. Unknown platforms default to
|
|
220
|
+
// the platform id itself as the provider id.
|
|
221
|
+
const platformToProvider = {
|
|
222
|
+
claude_api: 'anthropic',
|
|
223
|
+
openai: 'openai',
|
|
224
|
+
bedrock: 'bedrock',
|
|
225
|
+
};
|
|
226
|
+
const providerId = platformToProvider[platform] ?? platform;
|
|
227
|
+
// Build ToolDefinition[] from the resolved (available) tools.
|
|
228
|
+
const toolDefinitions = resolvedTools.map((rt) => {
|
|
229
|
+
let description = '';
|
|
230
|
+
try {
|
|
231
|
+
const catalogTool = toolStore.read(rt.canonicalName);
|
|
232
|
+
description = catalogTool.description;
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
// No catalog row — use the canonical name as a fallback description.
|
|
236
|
+
description = rt.canonicalName;
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
name: rt.canonicalName,
|
|
240
|
+
description,
|
|
241
|
+
inputSchema: {},
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
// emitToolsForProvider shapes each tool per the provider_tool_formats row.
|
|
245
|
+
// Double-cast via unknown: EmittedTool[] (EmittedServerSideTool lacks an
|
|
246
|
+
// index signature) → unknown[] → StructuredTool[]. Both types are
|
|
247
|
+
// compatible at runtime — all EmittedTool shapes are plain objects.
|
|
248
|
+
const emittedTools = emitToolsForProvider(toolDefinitions, providerId, lookupFmt);
|
|
249
|
+
const content = emitJsonObject({
|
|
250
|
+
agentSlug,
|
|
251
|
+
bodySections,
|
|
252
|
+
constraints,
|
|
253
|
+
tools: resolvedTools,
|
|
254
|
+
structuredTools: emittedTools,
|
|
255
|
+
model,
|
|
256
|
+
});
|
|
257
|
+
// ── 7a. Cache WRITE (MISS path) ────────────────────────────────────────
|
|
258
|
+
const written = cacheW(db, agentSlug, platform, context, componentVersions, content);
|
|
259
|
+
return { id: written.id, content, tools: emittedTools, componentVersions };
|
|
260
|
+
}
|
|
261
|
+
// none (cursor / vscode) — body only, no tools declaration ─────────────────
|
|
262
|
+
// Decision B.3: content = flat body + policy block, tools: [].
|
|
263
|
+
const bodyParts = [...bodySections];
|
|
264
|
+
if (constraints.length > 0) {
|
|
265
|
+
const policyLines = ['## Policies', ''];
|
|
266
|
+
for (const c of constraints) {
|
|
267
|
+
const prefix = c.inheritedFrom
|
|
268
|
+
? `(inherited from ${c.inheritedFrom}) `
|
|
269
|
+
: '';
|
|
270
|
+
policyLines.push(`- ${prefix}${c.text}`);
|
|
271
|
+
}
|
|
272
|
+
bodyParts.push(policyLines.join('\n'));
|
|
273
|
+
}
|
|
274
|
+
const content = bodyParts.join('\n\n') + '\n';
|
|
275
|
+
// ── 7a. Cache WRITE (MISS path) ─────────────────────────────────────────
|
|
276
|
+
const written = cacheW(db, agentSlug, platform, context, componentVersions, content);
|
|
277
|
+
return { id: written.id, content, tools: [], componentVersions };
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=compile.js.map
|