agent-contracts 0.11.2 → 0.11.4
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 +39 -1
- package/dist/cli.js +115 -62
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +72 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -297,7 +297,7 @@ Design regressions become testable.
|
|
|
297
297
|
* **Structured handoff definitions** with formal JSON Schema and `allOf` composition
|
|
298
298
|
* **Reusable schema components** via `components.schemas` and JSON Pointer `$ref`
|
|
299
299
|
* **Artifact ownership and lifecycle modeling**
|
|
300
|
-
* **Config-driven prompt rendering**
|
|
300
|
+
* **Config-driven prompt rendering** with `skip_empty` support for conditional file generation
|
|
301
301
|
* **Variable substitution** via `${vars.xxx}` in DSL values
|
|
302
302
|
* **Inheritance with merge operators via `extends`**
|
|
303
303
|
* **Guardrail definitions** for cross-cutting process constraints
|
|
@@ -865,6 +865,44 @@ This lets you generate static outputs for:
|
|
|
865
865
|
|
|
866
866
|
all from the same resolved DSL.
|
|
867
867
|
|
|
868
|
+
### Render target options
|
|
869
|
+
|
|
870
|
+
Each entry in `renders` supports these fields:
|
|
871
|
+
|
|
872
|
+
| Field | Type | Required | Description |
|
|
873
|
+
|-------|------|----------|-------------|
|
|
874
|
+
| `template` | string | yes | Path to Handlebars template |
|
|
875
|
+
| `context` | string | yes | Context type (see below) |
|
|
876
|
+
| `output` | string | yes | Output file path (supports `{<context>.id}` placeholder) |
|
|
877
|
+
| `include` | string[] | no | Only render these entity IDs (not with `system`) |
|
|
878
|
+
| `exclude` | string[] | no | Skip these entity IDs (not with `system`) |
|
|
879
|
+
| `skip_empty` | boolean | no | When `true`, if the rendered output is empty or whitespace-only, the file is **not written**. If the file already exists, it is **deleted**. |
|
|
880
|
+
|
|
881
|
+
#### `skip_empty` usage
|
|
882
|
+
|
|
883
|
+
`skip_empty` is useful when a single template applies to all entities of a context type, but only some entities produce meaningful output.
|
|
884
|
+
|
|
885
|
+
For example, when using `context: tool` to generate per-tool scripts, tools without an `x-script` property would produce empty files. With `skip_empty: true`, those files are simply not created:
|
|
886
|
+
|
|
887
|
+
````yaml
|
|
888
|
+
renders:
|
|
889
|
+
- template: ./templates/tool-script.sh.hbs
|
|
890
|
+
context: tool
|
|
891
|
+
output: ./output/scripts/{tool.id}.sh
|
|
892
|
+
skip_empty: true
|
|
893
|
+
````
|
|
894
|
+
|
|
895
|
+
````handlebars
|
|
896
|
+
{{!-- tool-script.sh.hbs --}}
|
|
897
|
+
{{#if tool.x-script}}
|
|
898
|
+
{{{tool.x-script}}}
|
|
899
|
+
{{/if}}
|
|
900
|
+
````
|
|
901
|
+
|
|
902
|
+
Tools with `x-script` get a generated script file; tools without it produce no file at all.
|
|
903
|
+
|
|
904
|
+
`skip_empty` also works with `render --check` (drift detection): when the expected output is empty, the check expects the file to **not exist** and reports drift if it does.
|
|
905
|
+
|
|
868
906
|
### Available context types
|
|
869
907
|
|
|
870
908
|
Each `context` type provides a different rendering scope:
|
package/dist/cli.js
CHANGED
|
@@ -159,11 +159,11 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
159
159
|
}
|
|
160
160
|
function __awaiter(thisArg, _arguments, P2, generator) {
|
|
161
161
|
function adopt(value) {
|
|
162
|
-
return value instanceof P2 ? value : new P2(function(
|
|
163
|
-
|
|
162
|
+
return value instanceof P2 ? value : new P2(function(resolve8) {
|
|
163
|
+
resolve8(value);
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
|
-
return new (P2 || (P2 = Promise))(function(
|
|
166
|
+
return new (P2 || (P2 = Promise))(function(resolve8, reject) {
|
|
167
167
|
function fulfilled(value) {
|
|
168
168
|
try {
|
|
169
169
|
step(generator.next(value));
|
|
@@ -179,7 +179,7 @@ function __awaiter(thisArg, _arguments, P2, generator) {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
function step(result) {
|
|
182
|
-
result.done ?
|
|
182
|
+
result.done ? resolve8(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
183
183
|
}
|
|
184
184
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
185
185
|
});
|
|
@@ -370,14 +370,14 @@ function __asyncValues(o3) {
|
|
|
370
370
|
}, i3);
|
|
371
371
|
function verb(n3) {
|
|
372
372
|
i3[n3] = o3[n3] && function(v2) {
|
|
373
|
-
return new Promise(function(
|
|
374
|
-
v2 = o3[n3](v2), settle(
|
|
373
|
+
return new Promise(function(resolve8, reject) {
|
|
374
|
+
v2 = o3[n3](v2), settle(resolve8, reject, v2.done, v2.value);
|
|
375
375
|
});
|
|
376
376
|
};
|
|
377
377
|
}
|
|
378
|
-
function settle(
|
|
378
|
+
function settle(resolve8, reject, d2, v2) {
|
|
379
379
|
Promise.resolve(v2).then(function(v3) {
|
|
380
|
-
|
|
380
|
+
resolve8({ value: v3, done: d2 });
|
|
381
381
|
}, reject);
|
|
382
382
|
}
|
|
383
383
|
}
|
|
@@ -13033,11 +13033,11 @@ function __metadata2(metadataKey, metadataValue) {
|
|
|
13033
13033
|
}
|
|
13034
13034
|
function __awaiter2(thisArg, _arguments, P2, generator) {
|
|
13035
13035
|
function adopt(value) {
|
|
13036
|
-
return value instanceof P2 ? value : new P2(function(
|
|
13037
|
-
|
|
13036
|
+
return value instanceof P2 ? value : new P2(function(resolve8) {
|
|
13037
|
+
resolve8(value);
|
|
13038
13038
|
});
|
|
13039
13039
|
}
|
|
13040
|
-
return new (P2 || (P2 = Promise))(function(
|
|
13040
|
+
return new (P2 || (P2 = Promise))(function(resolve8, reject) {
|
|
13041
13041
|
function fulfilled(value) {
|
|
13042
13042
|
try {
|
|
13043
13043
|
step(generator.next(value));
|
|
@@ -13053,7 +13053,7 @@ function __awaiter2(thisArg, _arguments, P2, generator) {
|
|
|
13053
13053
|
}
|
|
13054
13054
|
}
|
|
13055
13055
|
function step(result) {
|
|
13056
|
-
result.done ?
|
|
13056
|
+
result.done ? resolve8(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
13057
13057
|
}
|
|
13058
13058
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13059
13059
|
});
|
|
@@ -13231,14 +13231,14 @@ function __asyncValues2(o3) {
|
|
|
13231
13231
|
}, i3);
|
|
13232
13232
|
function verb(n3) {
|
|
13233
13233
|
i3[n3] = o3[n3] && function(v2) {
|
|
13234
|
-
return new Promise(function(
|
|
13235
|
-
v2 = o3[n3](v2), settle(
|
|
13234
|
+
return new Promise(function(resolve8, reject) {
|
|
13235
|
+
v2 = o3[n3](v2), settle(resolve8, reject, v2.done, v2.value);
|
|
13236
13236
|
});
|
|
13237
13237
|
};
|
|
13238
13238
|
}
|
|
13239
|
-
function settle(
|
|
13239
|
+
function settle(resolve8, reject, d2, v2) {
|
|
13240
13240
|
Promise.resolve(v2).then(function(v3) {
|
|
13241
|
-
|
|
13241
|
+
resolve8({ value: v3, done: d2 });
|
|
13242
13242
|
}, reject);
|
|
13243
13243
|
}
|
|
13244
13244
|
}
|
|
@@ -15152,7 +15152,7 @@ function consumeBody() {
|
|
|
15152
15152
|
let accum = [];
|
|
15153
15153
|
let accumBytes = 0;
|
|
15154
15154
|
let abort = false;
|
|
15155
|
-
return new Body.Promise(function(
|
|
15155
|
+
return new Body.Promise(function(resolve8, reject) {
|
|
15156
15156
|
let resTimeout;
|
|
15157
15157
|
if (_this4.timeout) {
|
|
15158
15158
|
resTimeout = setTimeout(function() {
|
|
@@ -15186,7 +15186,7 @@ function consumeBody() {
|
|
|
15186
15186
|
}
|
|
15187
15187
|
clearTimeout(resTimeout);
|
|
15188
15188
|
try {
|
|
15189
|
-
|
|
15189
|
+
resolve8(Buffer.concat(accum, accumBytes));
|
|
15190
15190
|
} catch (err) {
|
|
15191
15191
|
reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, "system", err));
|
|
15192
15192
|
}
|
|
@@ -15449,7 +15449,7 @@ function fetch(url, opts) {
|
|
|
15449
15449
|
throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
|
|
15450
15450
|
}
|
|
15451
15451
|
Body.Promise = fetch.Promise;
|
|
15452
|
-
return new fetch.Promise(function(
|
|
15452
|
+
return new fetch.Promise(function(resolve8, reject) {
|
|
15453
15453
|
const request = new Request(url, opts);
|
|
15454
15454
|
const options = getNodeRequestOptions(request);
|
|
15455
15455
|
const send = (options.protocol === "https:" ? https : http).request;
|
|
@@ -15582,7 +15582,7 @@ function fetch(url, opts) {
|
|
|
15582
15582
|
requestOpts.body = void 0;
|
|
15583
15583
|
requestOpts.headers.delete("content-length");
|
|
15584
15584
|
}
|
|
15585
|
-
|
|
15585
|
+
resolve8(fetch(new Request(locationURL, requestOpts)));
|
|
15586
15586
|
finalize();
|
|
15587
15587
|
return;
|
|
15588
15588
|
}
|
|
@@ -15603,7 +15603,7 @@ function fetch(url, opts) {
|
|
|
15603
15603
|
const codings = headers.get("Content-Encoding");
|
|
15604
15604
|
if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
|
|
15605
15605
|
response = new Response(body, response_options);
|
|
15606
|
-
|
|
15606
|
+
resolve8(response);
|
|
15607
15607
|
return;
|
|
15608
15608
|
}
|
|
15609
15609
|
const zlibOptions = {
|
|
@@ -15613,7 +15613,7 @@ function fetch(url, opts) {
|
|
|
15613
15613
|
if (codings == "gzip" || codings == "x-gzip") {
|
|
15614
15614
|
body = body.pipe(zlib.createGunzip(zlibOptions));
|
|
15615
15615
|
response = new Response(body, response_options);
|
|
15616
|
-
|
|
15616
|
+
resolve8(response);
|
|
15617
15617
|
return;
|
|
15618
15618
|
}
|
|
15619
15619
|
if (codings == "deflate" || codings == "x-deflate") {
|
|
@@ -15625,12 +15625,12 @@ function fetch(url, opts) {
|
|
|
15625
15625
|
body = body.pipe(zlib.createInflateRaw());
|
|
15626
15626
|
}
|
|
15627
15627
|
response = new Response(body, response_options);
|
|
15628
|
-
|
|
15628
|
+
resolve8(response);
|
|
15629
15629
|
});
|
|
15630
15630
|
raw.on("end", function() {
|
|
15631
15631
|
if (!response) {
|
|
15632
15632
|
response = new Response(body, response_options);
|
|
15633
|
-
|
|
15633
|
+
resolve8(response);
|
|
15634
15634
|
}
|
|
15635
15635
|
});
|
|
15636
15636
|
return;
|
|
@@ -15638,11 +15638,11 @@ function fetch(url, opts) {
|
|
|
15638
15638
|
if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
|
|
15639
15639
|
body = body.pipe(zlib.createBrotliDecompress());
|
|
15640
15640
|
response = new Response(body, response_options);
|
|
15641
|
-
|
|
15641
|
+
resolve8(response);
|
|
15642
15642
|
return;
|
|
15643
15643
|
}
|
|
15644
15644
|
response = new Response(body, response_options);
|
|
15645
|
-
|
|
15645
|
+
resolve8(response);
|
|
15646
15646
|
});
|
|
15647
15647
|
writeToStream(req, request);
|
|
15648
15648
|
});
|
|
@@ -16355,13 +16355,13 @@ var require_file = __commonJS({
|
|
|
16355
16355
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16356
16356
|
var fs_1 = __require("fs");
|
|
16357
16357
|
function resolveFile(ref) {
|
|
16358
|
-
return new Promise((
|
|
16358
|
+
return new Promise((resolve8, reject) => {
|
|
16359
16359
|
const path = ref.href();
|
|
16360
16360
|
fs_1.readFile(path, "utf8", (err, data) => {
|
|
16361
16361
|
if (err) {
|
|
16362
16362
|
reject(err);
|
|
16363
16363
|
} else {
|
|
16364
|
-
|
|
16364
|
+
resolve8(data);
|
|
16365
16365
|
}
|
|
16366
16366
|
});
|
|
16367
16367
|
});
|
|
@@ -23964,12 +23964,12 @@ var require_reader = __commonJS({
|
|
|
23964
23964
|
}
|
|
23965
23965
|
} else {
|
|
23966
23966
|
try {
|
|
23967
|
-
return await new Promise((
|
|
23967
|
+
return await new Promise((resolve8, reject) => {
|
|
23968
23968
|
fs.readFile(name, opts.encoding, (err, data) => {
|
|
23969
23969
|
if (err !== null) {
|
|
23970
23970
|
reject(err);
|
|
23971
23971
|
} else {
|
|
23972
|
-
|
|
23972
|
+
resolve8(data);
|
|
23973
23973
|
}
|
|
23974
23974
|
});
|
|
23975
23975
|
});
|
|
@@ -40854,14 +40854,14 @@ var require_AsyncFromSyncIteratorContinuation = __commonJS({
|
|
|
40854
40854
|
if (!$Promise) {
|
|
40855
40855
|
throw new $SyntaxError("This environment does not support Promises.");
|
|
40856
40856
|
}
|
|
40857
|
-
return new $Promise(function(
|
|
40857
|
+
return new $Promise(function(resolve8) {
|
|
40858
40858
|
var done = IteratorComplete(result);
|
|
40859
40859
|
var value = IteratorValue(result);
|
|
40860
40860
|
var valueWrapper = PromiseResolve($Promise, value);
|
|
40861
40861
|
var onFulfilled = function(value2) {
|
|
40862
40862
|
return CreateIteratorResultObject(value2, done);
|
|
40863
40863
|
};
|
|
40864
|
-
|
|
40864
|
+
resolve8($then(valueWrapper, onFulfilled));
|
|
40865
40865
|
});
|
|
40866
40866
|
};
|
|
40867
40867
|
}
|
|
@@ -41409,7 +41409,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
|
|
|
41409
41409
|
var O2 = this;
|
|
41410
41410
|
SLOT.assert(O2, "[[SyncIteratorRecord]]");
|
|
41411
41411
|
var argsLength = arguments.length;
|
|
41412
|
-
return new $Promise(function(
|
|
41412
|
+
return new $Promise(function(resolve8) {
|
|
41413
41413
|
var syncIteratorRecord = SLOT.get(O2, "[[SyncIteratorRecord]]");
|
|
41414
41414
|
var result;
|
|
41415
41415
|
if (argsLength > 0) {
|
|
@@ -41417,7 +41417,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
|
|
|
41417
41417
|
} else {
|
|
41418
41418
|
result = IteratorNext(syncIteratorRecord);
|
|
41419
41419
|
}
|
|
41420
|
-
|
|
41420
|
+
resolve8(AsyncFromSyncIteratorContinuation(result));
|
|
41421
41421
|
});
|
|
41422
41422
|
},
|
|
41423
41423
|
"return": function() {
|
|
@@ -41428,12 +41428,12 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
|
|
|
41428
41428
|
SLOT.assert(O2, "[[SyncIteratorRecord]]");
|
|
41429
41429
|
var valueIsPresent = arguments.length > 0;
|
|
41430
41430
|
var value = valueIsPresent ? arguments[0] : void 0;
|
|
41431
|
-
return new $Promise(function(
|
|
41431
|
+
return new $Promise(function(resolve8, reject) {
|
|
41432
41432
|
var syncIterator = SLOT.get(O2, "[[SyncIteratorRecord]]")["[[Iterator]]"];
|
|
41433
41433
|
var iteratorReturn = GetMethod(syncIterator, "return");
|
|
41434
41434
|
if (typeof iteratorReturn === "undefined") {
|
|
41435
41435
|
var iterResult = CreateIteratorResultObject(value, true);
|
|
41436
|
-
Call(
|
|
41436
|
+
Call(resolve8, void 0, [iterResult]);
|
|
41437
41437
|
return;
|
|
41438
41438
|
}
|
|
41439
41439
|
var result;
|
|
@@ -41446,7 +41446,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
|
|
|
41446
41446
|
Call(reject, void 0, [new $TypeError("Iterator `return` method returned a non-object value.")]);
|
|
41447
41447
|
return;
|
|
41448
41448
|
}
|
|
41449
|
-
|
|
41449
|
+
resolve8(AsyncFromSyncIteratorContinuation(result));
|
|
41450
41450
|
});
|
|
41451
41451
|
},
|
|
41452
41452
|
"throw": function() {
|
|
@@ -41457,7 +41457,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
|
|
|
41457
41457
|
SLOT.assert(O2, "[[SyncIteratorRecord]]");
|
|
41458
41458
|
var valueIsPresent = arguments.length > 0;
|
|
41459
41459
|
var value = valueIsPresent ? arguments[0] : void 0;
|
|
41460
|
-
return new $Promise(function(
|
|
41460
|
+
return new $Promise(function(resolve8, reject) {
|
|
41461
41461
|
var syncIterator = SLOT.get(O2, "[[SyncIteratorRecord]]")["[[Iterator]]"];
|
|
41462
41462
|
var throwMethod = GetMethod(syncIterator, "throw");
|
|
41463
41463
|
if (typeof throwMethod === "undefined") {
|
|
@@ -41474,7 +41474,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
|
|
|
41474
41474
|
Call(reject, void 0, [new $TypeError("Iterator `throw` method returned a non-object value.")]);
|
|
41475
41475
|
return;
|
|
41476
41476
|
}
|
|
41477
|
-
|
|
41477
|
+
resolve8(AsyncFromSyncIteratorContinuation(
|
|
41478
41478
|
result
|
|
41479
41479
|
/* , promiseCapability */
|
|
41480
41480
|
));
|
|
@@ -50425,6 +50425,9 @@ var require_dist13 = __commonJS({
|
|
|
50425
50425
|
});
|
|
50426
50426
|
|
|
50427
50427
|
// src/cli/cli.ts
|
|
50428
|
+
import { readFileSync } from "fs";
|
|
50429
|
+
import { fileURLToPath } from "url";
|
|
50430
|
+
import { resolve as resolve7, dirname as dirname7 } from "path";
|
|
50428
50431
|
import { Command as Command7 } from "commander";
|
|
50429
50432
|
|
|
50430
50433
|
// src/cli/commands/resolve.ts
|
|
@@ -50526,7 +50529,8 @@ var BindingOutputSchema = z3.object({
|
|
|
50526
50529
|
inline_template: z3.string().optional(),
|
|
50527
50530
|
mode: z3.enum(["write", "patch"]).default("write"),
|
|
50528
50531
|
group_by: z3.string().optional(),
|
|
50529
|
-
executable: z3.boolean().optional()
|
|
50532
|
+
executable: z3.boolean().optional(),
|
|
50533
|
+
skip_empty: z3.boolean().optional()
|
|
50530
50534
|
}).passthrough().refine(
|
|
50531
50535
|
(data) => !(data.template && data.inline_template),
|
|
50532
50536
|
{ message: "template and inline_template are mutually exclusive" }
|
|
@@ -50860,7 +50864,8 @@ var RenderTargetSchema = z14.object({
|
|
|
50860
50864
|
context: ContextTypeSchema,
|
|
50861
50865
|
output: z14.string(),
|
|
50862
50866
|
include: z14.array(z14.string()).optional(),
|
|
50863
|
-
exclude: z14.array(z14.string()).optional()
|
|
50867
|
+
exclude: z14.array(z14.string()).optional(),
|
|
50868
|
+
skip_empty: z14.boolean().optional()
|
|
50864
50869
|
}).refine(
|
|
50865
50870
|
(data) => !(data.include && data.exclude),
|
|
50866
50871
|
{ message: "include and exclude are mutually exclusive" }
|
|
@@ -53281,7 +53286,7 @@ var lintCommand = new Command3("lint").description("Run semantic lint rules on r
|
|
|
53281
53286
|
import { Command as Command4 } from "commander";
|
|
53282
53287
|
|
|
53283
53288
|
// src/renderer/renderer.ts
|
|
53284
|
-
import { readFile as readFile4, writeFile, mkdir } from "fs/promises";
|
|
53289
|
+
import { readFile as readFile4, writeFile, mkdir, unlink } from "fs/promises";
|
|
53285
53290
|
import { dirname as dirname5 } from "path";
|
|
53286
53291
|
import Handlebars from "handlebars";
|
|
53287
53292
|
|
|
@@ -54397,6 +54402,15 @@ function buildEntityContext(dsl, context, entityId) {
|
|
|
54397
54402
|
async function loadTemplate(templatePath) {
|
|
54398
54403
|
return readFile4(templatePath, "utf8");
|
|
54399
54404
|
}
|
|
54405
|
+
function isEffectivelyEmpty(output) {
|
|
54406
|
+
return output.trim().length === 0;
|
|
54407
|
+
}
|
|
54408
|
+
async function removeIfExists(filePath) {
|
|
54409
|
+
try {
|
|
54410
|
+
await unlink(filePath);
|
|
54411
|
+
} catch {
|
|
54412
|
+
}
|
|
54413
|
+
}
|
|
54400
54414
|
async function renderFromConfig(dsl, renderTargets) {
|
|
54401
54415
|
const outputFiles = [];
|
|
54402
54416
|
for (const target of renderTargets) {
|
|
@@ -54405,6 +54419,10 @@ async function renderFromConfig(dsl, renderTargets) {
|
|
|
54405
54419
|
if (target.context === "system") {
|
|
54406
54420
|
const ctx = buildSystemContext(dsl);
|
|
54407
54421
|
const output = compiled(ctx);
|
|
54422
|
+
if (target.skip_empty && isEffectivelyEmpty(output)) {
|
|
54423
|
+
await removeIfExists(target.output);
|
|
54424
|
+
continue;
|
|
54425
|
+
}
|
|
54408
54426
|
await mkdir(dirname5(target.output), { recursive: true });
|
|
54409
54427
|
await writeFile(target.output, output, "utf8");
|
|
54410
54428
|
outputFiles.push(target.output);
|
|
@@ -54416,6 +54434,10 @@ async function renderFromConfig(dsl, renderTargets) {
|
|
|
54416
54434
|
const ctx = buildEntityContext(dsl, target.context, entityId);
|
|
54417
54435
|
const output = compiled(ctx);
|
|
54418
54436
|
const outputPath = expandOutputPath(target.output, target.context, entityId);
|
|
54437
|
+
if (target.skip_empty && isEffectivelyEmpty(output)) {
|
|
54438
|
+
await removeIfExists(outputPath);
|
|
54439
|
+
continue;
|
|
54440
|
+
}
|
|
54419
54441
|
await mkdir(dirname5(outputPath), { recursive: true });
|
|
54420
54442
|
await writeFile(outputPath, output, "utf8");
|
|
54421
54443
|
outputFiles.push(outputPath);
|
|
@@ -54424,6 +54446,26 @@ async function renderFromConfig(dsl, renderTargets) {
|
|
|
54424
54446
|
}
|
|
54425
54447
|
return outputFiles;
|
|
54426
54448
|
}
|
|
54449
|
+
async function fileExists2(filePath) {
|
|
54450
|
+
try {
|
|
54451
|
+
await readFile4(filePath);
|
|
54452
|
+
return true;
|
|
54453
|
+
} catch {
|
|
54454
|
+
return false;
|
|
54455
|
+
}
|
|
54456
|
+
}
|
|
54457
|
+
function checkExpectedVsExisting(expected, outputPath, skipEmpty, diffs) {
|
|
54458
|
+
if (skipEmpty && isEffectivelyEmpty(expected)) {
|
|
54459
|
+
return fileExists2(outputPath).then((exists) => {
|
|
54460
|
+
if (exists) diffs.push(outputPath);
|
|
54461
|
+
});
|
|
54462
|
+
}
|
|
54463
|
+
return readFile4(outputPath, "utf8").then((existing) => {
|
|
54464
|
+
if (existing !== expected) diffs.push(outputPath);
|
|
54465
|
+
}).catch(() => {
|
|
54466
|
+
diffs.push(outputPath);
|
|
54467
|
+
});
|
|
54468
|
+
}
|
|
54427
54469
|
async function checkDriftFromConfig(dsl, renderTargets) {
|
|
54428
54470
|
const diffs = [];
|
|
54429
54471
|
for (const target of renderTargets) {
|
|
@@ -54432,12 +54474,7 @@ async function checkDriftFromConfig(dsl, renderTargets) {
|
|
|
54432
54474
|
if (target.context === "system") {
|
|
54433
54475
|
const ctx = buildSystemContext(dsl);
|
|
54434
54476
|
const expected = compiled(ctx);
|
|
54435
|
-
|
|
54436
|
-
const existing = await readFile4(target.output, "utf8");
|
|
54437
|
-
if (existing !== expected) diffs.push(target.output);
|
|
54438
|
-
} catch {
|
|
54439
|
-
diffs.push(target.output);
|
|
54440
|
-
}
|
|
54477
|
+
await checkExpectedVsExisting(expected, target.output, target.skip_empty, diffs);
|
|
54441
54478
|
} else {
|
|
54442
54479
|
const section = getDslSection(dsl, target.context);
|
|
54443
54480
|
const allIds = Object.keys(section);
|
|
@@ -54446,12 +54483,7 @@ async function checkDriftFromConfig(dsl, renderTargets) {
|
|
|
54446
54483
|
const ctx = buildEntityContext(dsl, target.context, entityId);
|
|
54447
54484
|
const expected = compiled(ctx);
|
|
54448
54485
|
const outputPath = expandOutputPath(target.output, target.context, entityId);
|
|
54449
|
-
|
|
54450
|
-
const existing = await readFile4(outputPath, "utf8");
|
|
54451
|
-
if (existing !== expected) diffs.push(outputPath);
|
|
54452
|
-
} catch {
|
|
54453
|
-
diffs.push(outputPath);
|
|
54454
|
-
}
|
|
54486
|
+
await checkExpectedVsExisting(expected, outputPath, target.skip_empty, diffs);
|
|
54455
54487
|
}
|
|
54456
54488
|
}
|
|
54457
54489
|
}
|
|
@@ -54609,7 +54641,7 @@ var checkCommand = new Command5("check").description("Run full pipeline: resolve
|
|
|
54609
54641
|
import { Command as Command6 } from "commander";
|
|
54610
54642
|
|
|
54611
54643
|
// src/guardrail-generator/generator.ts
|
|
54612
|
-
import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod } from "fs/promises";
|
|
54644
|
+
import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod, unlink as unlink2 } from "fs/promises";
|
|
54613
54645
|
import { resolve as resolve6, dirname as dirname6 } from "path";
|
|
54614
54646
|
import Handlebars2 from "handlebars";
|
|
54615
54647
|
|
|
@@ -54783,6 +54815,7 @@ async function generateGuardrails(options) {
|
|
|
54783
54815
|
});
|
|
54784
54816
|
continue;
|
|
54785
54817
|
}
|
|
54818
|
+
const shouldSkipEmpty = outputDef.skip_empty === true;
|
|
54786
54819
|
if (outputDef.group_by) {
|
|
54787
54820
|
const groupField = outputDef.group_by;
|
|
54788
54821
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -54802,6 +54835,15 @@ async function generateGuardrails(options) {
|
|
|
54802
54835
|
const compiled = Handlebars2.compile(templateContent, { noEscape: true });
|
|
54803
54836
|
const output = compiled(groupCtx);
|
|
54804
54837
|
const groupTarget = resolve6(targetPath, groupKey);
|
|
54838
|
+
if (shouldSkipEmpty && output.trim().length === 0) {
|
|
54839
|
+
if (!dryRun) {
|
|
54840
|
+
try {
|
|
54841
|
+
await unlink2(groupTarget);
|
|
54842
|
+
} catch {
|
|
54843
|
+
}
|
|
54844
|
+
}
|
|
54845
|
+
continue;
|
|
54846
|
+
}
|
|
54805
54847
|
if (!dryRun) {
|
|
54806
54848
|
await mkdir2(dirname6(groupTarget), { recursive: true });
|
|
54807
54849
|
await writeFile2(groupTarget, output, "utf8");
|
|
@@ -54814,14 +54856,23 @@ async function generateGuardrails(options) {
|
|
|
54814
54856
|
} else {
|
|
54815
54857
|
const compiled = Handlebars2.compile(templateContent, { noEscape: true });
|
|
54816
54858
|
const output = compiled(ctx);
|
|
54817
|
-
if (
|
|
54818
|
-
|
|
54819
|
-
|
|
54820
|
-
|
|
54821
|
-
|
|
54859
|
+
if (shouldSkipEmpty && output.trim().length === 0) {
|
|
54860
|
+
if (!dryRun) {
|
|
54861
|
+
try {
|
|
54862
|
+
await unlink2(targetPath);
|
|
54863
|
+
} catch {
|
|
54864
|
+
}
|
|
54865
|
+
}
|
|
54866
|
+
} else {
|
|
54867
|
+
if (!dryRun) {
|
|
54868
|
+
await mkdir2(dirname6(targetPath), { recursive: true });
|
|
54869
|
+
await writeFile2(targetPath, output, "utf8");
|
|
54870
|
+
if (outputDef.executable) {
|
|
54871
|
+
await chmod(targetPath, 493);
|
|
54872
|
+
}
|
|
54822
54873
|
}
|
|
54874
|
+
outputFiles.push(targetPath);
|
|
54823
54875
|
}
|
|
54824
|
-
outputFiles.push(targetPath);
|
|
54825
54876
|
}
|
|
54826
54877
|
}
|
|
54827
54878
|
}
|
|
@@ -54913,8 +54964,10 @@ var generateGuardrailsCommand = new Command6("generate").description("Generate g
|
|
|
54913
54964
|
);
|
|
54914
54965
|
|
|
54915
54966
|
// src/cli/cli.ts
|
|
54967
|
+
var __dirname = dirname7(fileURLToPath(import.meta.url));
|
|
54968
|
+
var pkg = JSON.parse(readFileSync(resolve7(__dirname, "../package.json"), "utf8"));
|
|
54916
54969
|
var program = new Command7();
|
|
54917
|
-
program.name("agent-contracts").description("Agent contracts tooling \u2014 validate, lint, render DSL files").version(
|
|
54970
|
+
program.name("agent-contracts").description("Agent contracts tooling \u2014 validate, lint, render DSL files").version(pkg.version);
|
|
54918
54971
|
program.addCommand(resolveCommand);
|
|
54919
54972
|
program.addCommand(validateCommand);
|
|
54920
54973
|
program.addCommand(lintCommand);
|