agent-contracts 0.11.0 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -0
- package/dist/cli.js +198 -95
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +12 -9
- package/dist/index.js +168 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1003,6 +1003,76 @@ outputs:
|
|
|
1003
1003
|
template: ./templates/cursor-hook-wrapper.sh.hbs
|
|
1004
1004
|
````
|
|
1005
1005
|
|
|
1006
|
+
### Binding inheritance
|
|
1007
|
+
|
|
1008
|
+
Binding files support `extends` for inheriting and extending a base binding, using the same mechanism as DSL-level `extends`.
|
|
1009
|
+
|
|
1010
|
+
A base binding defines shared guardrail implementations and outputs:
|
|
1011
|
+
|
|
1012
|
+
````yaml
|
|
1013
|
+
# skeleton/bindings/cursor.yaml (base)
|
|
1014
|
+
software: cursor
|
|
1015
|
+
version: 1
|
|
1016
|
+
|
|
1017
|
+
guardrail_impl:
|
|
1018
|
+
no-force-push:
|
|
1019
|
+
checks:
|
|
1020
|
+
- hook_event: beforeShellExecution
|
|
1021
|
+
matcher:
|
|
1022
|
+
type: command_regex
|
|
1023
|
+
pattern: "git\\s+push\\s+.*--force"
|
|
1024
|
+
message: "Force push is forbidden"
|
|
1025
|
+
|
|
1026
|
+
outputs:
|
|
1027
|
+
policy-bundle:
|
|
1028
|
+
target: "{cursor_root}/guardrails/policy.json"
|
|
1029
|
+
mode: write
|
|
1030
|
+
inline_template: "{{json resolved_checks}}"
|
|
1031
|
+
````
|
|
1032
|
+
|
|
1033
|
+
A project binding extends the base and adds project-specific guardrail implementations:
|
|
1034
|
+
|
|
1035
|
+
````yaml
|
|
1036
|
+
# project/bindings/cursor.yaml
|
|
1037
|
+
extends: ../../skeleton/bindings/cursor.yaml
|
|
1038
|
+
software: cursor
|
|
1039
|
+
version: 1
|
|
1040
|
+
|
|
1041
|
+
guardrail_impl:
|
|
1042
|
+
lint-on-save:
|
|
1043
|
+
checks:
|
|
1044
|
+
- hook_event: afterFileEdit
|
|
1045
|
+
matcher:
|
|
1046
|
+
type: file_glob
|
|
1047
|
+
pattern: "**/*.{ts,tsx}"
|
|
1048
|
+
message: "TS file edited — lint results attached."
|
|
1049
|
+
````
|
|
1050
|
+
|
|
1051
|
+
The result is a single merged binding with all guardrail implementations from both base and project.
|
|
1052
|
+
|
|
1053
|
+
Merge behavior:
|
|
1054
|
+
|
|
1055
|
+
| Field | Behavior |
|
|
1056
|
+
|-------|----------|
|
|
1057
|
+
| `software` | Project wins |
|
|
1058
|
+
| `guardrail_impl` | Map merge by guardrail ID (new IDs added; same ID deep-merged) |
|
|
1059
|
+
| `outputs` | Map merge by output ID (project overrides base) |
|
|
1060
|
+
| `reporting` | Deep merge (project fields override base) |
|
|
1061
|
+
| passthrough fields | Project wins |
|
|
1062
|
+
|
|
1063
|
+
All merge operators (`$append`, `$prepend`, `$insert_after`, `$replace`, `$remove`) work within binding `extends`, the same as DSL `extends`.
|
|
1064
|
+
|
|
1065
|
+
Chained inheritance (grandparent → parent → child) and both local path (`./`, `../`) and npm package references are supported. Circular extends are detected and rejected.
|
|
1066
|
+
|
|
1067
|
+
When using binding `extends`, the config only needs to list the child binding:
|
|
1068
|
+
|
|
1069
|
+
````yaml
|
|
1070
|
+
# agent-contracts.config.yaml
|
|
1071
|
+
bindings:
|
|
1072
|
+
- ./bindings/cursor.yaml # extends base internally
|
|
1073
|
+
- ./bindings/git.yaml
|
|
1074
|
+
````
|
|
1075
|
+
|
|
1006
1076
|
### Config
|
|
1007
1077
|
|
|
1008
1078
|
````yaml
|
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(resolve7) {
|
|
163
|
+
resolve7(value);
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
|
-
return new (P2 || (P2 = Promise))(function(
|
|
166
|
+
return new (P2 || (P2 = Promise))(function(resolve7, 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 ? resolve7(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(resolve7, reject) {
|
|
374
|
+
v2 = o3[n3](v2), settle(resolve7, reject, v2.done, v2.value);
|
|
375
375
|
});
|
|
376
376
|
};
|
|
377
377
|
}
|
|
378
|
-
function settle(
|
|
378
|
+
function settle(resolve7, reject, d2, v2) {
|
|
379
379
|
Promise.resolve(v2).then(function(v3) {
|
|
380
|
-
|
|
380
|
+
resolve7({ 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(resolve7) {
|
|
13037
|
+
resolve7(value);
|
|
13038
13038
|
});
|
|
13039
13039
|
}
|
|
13040
|
-
return new (P2 || (P2 = Promise))(function(
|
|
13040
|
+
return new (P2 || (P2 = Promise))(function(resolve7, 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 ? resolve7(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(resolve7, reject) {
|
|
13235
|
+
v2 = o3[n3](v2), settle(resolve7, reject, v2.done, v2.value);
|
|
13236
13236
|
});
|
|
13237
13237
|
};
|
|
13238
13238
|
}
|
|
13239
|
-
function settle(
|
|
13239
|
+
function settle(resolve7, reject, d2, v2) {
|
|
13240
13240
|
Promise.resolve(v2).then(function(v3) {
|
|
13241
|
-
|
|
13241
|
+
resolve7({ 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(resolve7, 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
|
+
resolve7(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(resolve7, 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
|
+
resolve7(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
|
+
resolve7(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
|
+
resolve7(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
|
+
resolve7(response);
|
|
15629
15629
|
});
|
|
15630
15630
|
raw.on("end", function() {
|
|
15631
15631
|
if (!response) {
|
|
15632
15632
|
response = new Response(body, response_options);
|
|
15633
|
-
|
|
15633
|
+
resolve7(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
|
+
resolve7(response);
|
|
15642
15642
|
return;
|
|
15643
15643
|
}
|
|
15644
15644
|
response = new Response(body, response_options);
|
|
15645
|
-
|
|
15645
|
+
resolve7(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((resolve7, 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
|
+
resolve7(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((resolve7, reject) => {
|
|
23968
23968
|
fs.readFile(name, opts.encoding, (err, data) => {
|
|
23969
23969
|
if (err !== null) {
|
|
23970
23970
|
reject(err);
|
|
23971
23971
|
} else {
|
|
23972
|
-
|
|
23972
|
+
resolve7(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(resolve7) {
|
|
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
|
+
resolve7($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(resolve7) {
|
|
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
|
+
resolve7(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(resolve7, 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(resolve7, 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
|
+
resolve7(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(resolve7, 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
|
+
resolve7(AsyncFromSyncIteratorContinuation(
|
|
41478
41478
|
result
|
|
41479
41479
|
/* , promiseCapability */
|
|
41480
41480
|
));
|
|
@@ -50431,8 +50431,10 @@ import { Command as Command7 } from "commander";
|
|
|
50431
50431
|
import { Command } from "commander";
|
|
50432
50432
|
|
|
50433
50433
|
// src/config/binding-loader.ts
|
|
50434
|
-
import { readFile as
|
|
50435
|
-
import {
|
|
50434
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
50435
|
+
import { dirname as dirname4, resolve as resolve5 } from "path";
|
|
50436
|
+
import { stat as stat2 } from "fs/promises";
|
|
50437
|
+
import { parse as parseYaml3 } from "yaml";
|
|
50436
50438
|
|
|
50437
50439
|
// src/schema/agent.ts
|
|
50438
50440
|
import { z } from "zod";
|
|
@@ -50496,17 +50498,18 @@ import { z as z3 } from "zod";
|
|
|
50496
50498
|
var CommandRegexMatcherSchema = z3.object({
|
|
50497
50499
|
type: z3.literal("command_regex"),
|
|
50498
50500
|
pattern: z3.string()
|
|
50499
|
-
});
|
|
50501
|
+
}).passthrough();
|
|
50500
50502
|
var ContentRegexMatcherSchema = z3.object({
|
|
50501
50503
|
type: z3.literal("content_regex"),
|
|
50502
50504
|
pattern: z3.string(),
|
|
50503
50505
|
file_glob: z3.string().optional(),
|
|
50504
50506
|
exclude_glob: z3.string().optional()
|
|
50505
|
-
});
|
|
50507
|
+
}).passthrough();
|
|
50506
50508
|
var FileGlobMatcherSchema = z3.object({
|
|
50507
50509
|
type: z3.literal("file_glob"),
|
|
50508
|
-
pattern: z3.string()
|
|
50509
|
-
|
|
50510
|
+
pattern: z3.string(),
|
|
50511
|
+
exclude_glob: z3.string().optional()
|
|
50512
|
+
}).passthrough();
|
|
50510
50513
|
var MatcherSchema = z3.discriminatedUnion("type", [
|
|
50511
50514
|
CommandRegexMatcherSchema,
|
|
50512
50515
|
ContentRegexMatcherSchema,
|
|
@@ -50963,51 +50966,14 @@ function resolveDslPath(dirArg, dirArgDefault, config) {
|
|
|
50963
50966
|
return resolve(dirArgDefault);
|
|
50964
50967
|
}
|
|
50965
50968
|
|
|
50966
|
-
// src/config/binding-loader.ts
|
|
50967
|
-
async function loadBindings(bindingPaths) {
|
|
50968
|
-
const results = [];
|
|
50969
|
-
for (const filePath of bindingPaths) {
|
|
50970
|
-
let content;
|
|
50971
|
-
try {
|
|
50972
|
-
content = await readFile2(filePath, "utf8");
|
|
50973
|
-
} catch {
|
|
50974
|
-
throw new ConfigLoadError(
|
|
50975
|
-
`Failed to read binding file: ${filePath}`,
|
|
50976
|
-
filePath
|
|
50977
|
-
);
|
|
50978
|
-
}
|
|
50979
|
-
let raw;
|
|
50980
|
-
try {
|
|
50981
|
-
raw = parseYaml2(content);
|
|
50982
|
-
} catch (err) {
|
|
50983
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
50984
|
-
throw new ConfigLoadError(
|
|
50985
|
-
`Invalid YAML syntax in binding file ${filePath}: ${msg}`,
|
|
50986
|
-
filePath
|
|
50987
|
-
);
|
|
50988
|
-
}
|
|
50989
|
-
const result = SoftwareBindingSchema.safeParse(raw);
|
|
50990
|
-
if (!result.success) {
|
|
50991
|
-
const issues = result.error.issues.map((i3) => ` ${i3.path.join(".")}: ${i3.message}`).join("\n");
|
|
50992
|
-
throw new ConfigLoadError(
|
|
50993
|
-
`Invalid binding schema in ${filePath}:
|
|
50994
|
-
${issues}`,
|
|
50995
|
-
filePath
|
|
50996
|
-
);
|
|
50997
|
-
}
|
|
50998
|
-
results.push({ filePath, binding: result.data });
|
|
50999
|
-
}
|
|
51000
|
-
return results;
|
|
51001
|
-
}
|
|
51002
|
-
|
|
51003
50969
|
// src/resolver/base-resolver.ts
|
|
51004
50970
|
import { resolve as resolve3, join as join2 } from "path";
|
|
51005
50971
|
import { stat } from "fs/promises";
|
|
51006
50972
|
|
|
51007
50973
|
// src/loader/loader.ts
|
|
51008
|
-
import { readFile as
|
|
50974
|
+
import { readFile as readFile2, readdir, stat as fsStat } from "fs/promises";
|
|
51009
50975
|
import { dirname as dirname2, resolve as resolve2, join, extname } from "path";
|
|
51010
|
-
import { parse as
|
|
50976
|
+
import { parse as parseYaml2 } from "yaml";
|
|
51011
50977
|
var DslLoadError = class extends Error {
|
|
51012
50978
|
constructor(message, filePath) {
|
|
51013
50979
|
super(message);
|
|
@@ -51060,7 +51026,7 @@ function hasRefs(value) {
|
|
|
51060
51026
|
async function readYaml(filePath) {
|
|
51061
51027
|
let content;
|
|
51062
51028
|
try {
|
|
51063
|
-
content = await
|
|
51029
|
+
content = await readFile2(filePath, "utf8");
|
|
51064
51030
|
} catch {
|
|
51065
51031
|
throw new DslLoadError(
|
|
51066
51032
|
`File not found: ${filePath}`,
|
|
@@ -51068,7 +51034,7 @@ async function readYaml(filePath) {
|
|
|
51068
51034
|
);
|
|
51069
51035
|
}
|
|
51070
51036
|
try {
|
|
51071
|
-
return
|
|
51037
|
+
return parseYaml2(content);
|
|
51072
51038
|
} catch (err) {
|
|
51073
51039
|
const msg = err instanceof Error ? err.message : String(err);
|
|
51074
51040
|
throw new DslLoadError(
|
|
@@ -51649,6 +51615,143 @@ function substituteVars(data, vars) {
|
|
|
51649
51615
|
return walk(data, vars);
|
|
51650
51616
|
}
|
|
51651
51617
|
|
|
51618
|
+
// src/config/binding-merger.ts
|
|
51619
|
+
function isRecord3(v2) {
|
|
51620
|
+
return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
|
|
51621
|
+
}
|
|
51622
|
+
var BINDING_MERGE_SECTIONS = ["guardrail_impl", "outputs"];
|
|
51623
|
+
function mergeBinding(base, project) {
|
|
51624
|
+
const hasExtends = typeof project["extends"] === "string";
|
|
51625
|
+
const result = { ...base, ...project };
|
|
51626
|
+
for (const section of BINDING_MERGE_SECTIONS) {
|
|
51627
|
+
const baseVal = base[section];
|
|
51628
|
+
const projVal = project[section];
|
|
51629
|
+
if (projVal === void 0) {
|
|
51630
|
+
continue;
|
|
51631
|
+
}
|
|
51632
|
+
const baseMap = isRecord3(baseVal) ? baseVal : {};
|
|
51633
|
+
result[section] = mergeEntityMaps(
|
|
51634
|
+
baseMap,
|
|
51635
|
+
projVal,
|
|
51636
|
+
section,
|
|
51637
|
+
hasExtends
|
|
51638
|
+
);
|
|
51639
|
+
}
|
|
51640
|
+
if (project["reporting"] !== void 0 && isRecord3(base["reporting"]) && isRecord3(project["reporting"])) {
|
|
51641
|
+
result["reporting"] = deepMergeEntities(
|
|
51642
|
+
base["reporting"],
|
|
51643
|
+
project["reporting"],
|
|
51644
|
+
"reporting",
|
|
51645
|
+
hasExtends
|
|
51646
|
+
);
|
|
51647
|
+
}
|
|
51648
|
+
delete result["extends"];
|
|
51649
|
+
return result;
|
|
51650
|
+
}
|
|
51651
|
+
|
|
51652
|
+
// src/config/binding-loader.ts
|
|
51653
|
+
async function loadRawBinding(filePath) {
|
|
51654
|
+
let content;
|
|
51655
|
+
try {
|
|
51656
|
+
content = await readFile3(filePath, "utf8");
|
|
51657
|
+
} catch {
|
|
51658
|
+
throw new ConfigLoadError(
|
|
51659
|
+
`Failed to read binding file: ${filePath}`,
|
|
51660
|
+
filePath
|
|
51661
|
+
);
|
|
51662
|
+
}
|
|
51663
|
+
try {
|
|
51664
|
+
return parseYaml3(content);
|
|
51665
|
+
} catch (err) {
|
|
51666
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
51667
|
+
throw new ConfigLoadError(
|
|
51668
|
+
`Invalid YAML syntax in binding file ${filePath}: ${msg}`,
|
|
51669
|
+
filePath
|
|
51670
|
+
);
|
|
51671
|
+
}
|
|
51672
|
+
}
|
|
51673
|
+
async function resolveBindingExtends(raw, filePath, seen) {
|
|
51674
|
+
const extendsValue = raw["extends"];
|
|
51675
|
+
if (typeof extendsValue !== "string") {
|
|
51676
|
+
return raw;
|
|
51677
|
+
}
|
|
51678
|
+
const bindingDir = dirname4(filePath);
|
|
51679
|
+
let basePath;
|
|
51680
|
+
if (extendsValue.startsWith("./") || extendsValue.startsWith("../")) {
|
|
51681
|
+
basePath = resolve5(bindingDir, extendsValue);
|
|
51682
|
+
} else {
|
|
51683
|
+
try {
|
|
51684
|
+
const resolved = import.meta.resolve(extendsValue);
|
|
51685
|
+
basePath = new URL(resolved).pathname;
|
|
51686
|
+
} catch {
|
|
51687
|
+
throw new ConfigLoadError(
|
|
51688
|
+
`Could not resolve binding extends package: ${extendsValue}`,
|
|
51689
|
+
filePath
|
|
51690
|
+
);
|
|
51691
|
+
}
|
|
51692
|
+
}
|
|
51693
|
+
try {
|
|
51694
|
+
const s2 = await stat2(basePath);
|
|
51695
|
+
if (s2.isDirectory()) {
|
|
51696
|
+
const candidates = ["binding.yaml", "binding.yml"];
|
|
51697
|
+
let found = false;
|
|
51698
|
+
for (const name of candidates) {
|
|
51699
|
+
const candidate = resolve5(basePath, name);
|
|
51700
|
+
try {
|
|
51701
|
+
const cs = await stat2(candidate);
|
|
51702
|
+
if (cs.isFile()) {
|
|
51703
|
+
basePath = candidate;
|
|
51704
|
+
found = true;
|
|
51705
|
+
break;
|
|
51706
|
+
}
|
|
51707
|
+
} catch {
|
|
51708
|
+
continue;
|
|
51709
|
+
}
|
|
51710
|
+
}
|
|
51711
|
+
if (!found) {
|
|
51712
|
+
throw new ConfigLoadError(
|
|
51713
|
+
`No binding.yaml found in directory: ${basePath}`,
|
|
51714
|
+
filePath
|
|
51715
|
+
);
|
|
51716
|
+
}
|
|
51717
|
+
}
|
|
51718
|
+
} catch (err) {
|
|
51719
|
+
if (err instanceof ConfigLoadError) throw err;
|
|
51720
|
+
throw new ConfigLoadError(
|
|
51721
|
+
`Base binding path not found: ${basePath}`,
|
|
51722
|
+
filePath
|
|
51723
|
+
);
|
|
51724
|
+
}
|
|
51725
|
+
if (seen.has(basePath)) {
|
|
51726
|
+
throw new ConfigLoadError(
|
|
51727
|
+
`Circular binding extends detected: ${basePath}`,
|
|
51728
|
+
filePath
|
|
51729
|
+
);
|
|
51730
|
+
}
|
|
51731
|
+
seen.add(basePath);
|
|
51732
|
+
const baseRaw = await loadRawBinding(basePath);
|
|
51733
|
+
const resolvedBase = await resolveBindingExtends(baseRaw, basePath, seen);
|
|
51734
|
+
return mergeBinding(resolvedBase, raw);
|
|
51735
|
+
}
|
|
51736
|
+
async function loadBindings(bindingPaths) {
|
|
51737
|
+
const results = [];
|
|
51738
|
+
for (const filePath of bindingPaths) {
|
|
51739
|
+
const raw = await loadRawBinding(filePath);
|
|
51740
|
+
const merged = await resolveBindingExtends(raw, filePath, /* @__PURE__ */ new Set([filePath]));
|
|
51741
|
+
const result = SoftwareBindingSchema.safeParse(merged);
|
|
51742
|
+
if (!result.success) {
|
|
51743
|
+
const issues = result.error.issues.map((i3) => ` ${i3.path.join(".")}: ${i3.message}`).join("\n");
|
|
51744
|
+
throw new ConfigLoadError(
|
|
51745
|
+
`Invalid binding schema in ${filePath}:
|
|
51746
|
+
${issues}`,
|
|
51747
|
+
filePath
|
|
51748
|
+
);
|
|
51749
|
+
}
|
|
51750
|
+
results.push({ filePath, binding: result.data });
|
|
51751
|
+
}
|
|
51752
|
+
return results;
|
|
51753
|
+
}
|
|
51754
|
+
|
|
51652
51755
|
// src/cli/commands/resolve.ts
|
|
51653
51756
|
import { stringify } from "yaml";
|
|
51654
51757
|
var DIR_DEFAULT = "agent-contracts.yaml";
|
|
@@ -53179,7 +53282,7 @@ import { Command as Command4 } from "commander";
|
|
|
53179
53282
|
|
|
53180
53283
|
// src/renderer/renderer.ts
|
|
53181
53284
|
import { readFile as readFile4, writeFile, mkdir } from "fs/promises";
|
|
53182
|
-
import { dirname as
|
|
53285
|
+
import { dirname as dirname5 } from "path";
|
|
53183
53286
|
import Handlebars from "handlebars";
|
|
53184
53287
|
|
|
53185
53288
|
// src/renderer/context.ts
|
|
@@ -54302,7 +54405,7 @@ async function renderFromConfig(dsl, renderTargets) {
|
|
|
54302
54405
|
if (target.context === "system") {
|
|
54303
54406
|
const ctx = buildSystemContext(dsl);
|
|
54304
54407
|
const output = compiled(ctx);
|
|
54305
|
-
await mkdir(
|
|
54408
|
+
await mkdir(dirname5(target.output), { recursive: true });
|
|
54306
54409
|
await writeFile(target.output, output, "utf8");
|
|
54307
54410
|
outputFiles.push(target.output);
|
|
54308
54411
|
} else {
|
|
@@ -54313,7 +54416,7 @@ async function renderFromConfig(dsl, renderTargets) {
|
|
|
54313
54416
|
const ctx = buildEntityContext(dsl, target.context, entityId);
|
|
54314
54417
|
const output = compiled(ctx);
|
|
54315
54418
|
const outputPath = expandOutputPath(target.output, target.context, entityId);
|
|
54316
|
-
await mkdir(
|
|
54419
|
+
await mkdir(dirname5(outputPath), { recursive: true });
|
|
54317
54420
|
await writeFile(outputPath, output, "utf8");
|
|
54318
54421
|
outputFiles.push(outputPath);
|
|
54319
54422
|
}
|
|
@@ -54507,7 +54610,7 @@ import { Command as Command6 } from "commander";
|
|
|
54507
54610
|
|
|
54508
54611
|
// src/guardrail-generator/generator.ts
|
|
54509
54612
|
import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod } from "fs/promises";
|
|
54510
|
-
import { resolve as
|
|
54613
|
+
import { resolve as resolve6, dirname as dirname6 } from "path";
|
|
54511
54614
|
import Handlebars2 from "handlebars";
|
|
54512
54615
|
|
|
54513
54616
|
// src/guardrail-generator/resolve-checks.ts
|
|
@@ -54648,7 +54751,7 @@ async function generateGuardrails(options) {
|
|
|
54648
54751
|
if (pathResult.diagnostics.some((d2) => d2.severity === "error")) {
|
|
54649
54752
|
continue;
|
|
54650
54753
|
}
|
|
54651
|
-
const targetPath =
|
|
54754
|
+
const targetPath = resolve6(config.configDir, pathResult.resolved);
|
|
54652
54755
|
let templateContent;
|
|
54653
54756
|
if (outputDef.inline_template) {
|
|
54654
54757
|
templateContent = outputDef.inline_template;
|
|
@@ -54661,7 +54764,7 @@ async function generateGuardrails(options) {
|
|
|
54661
54764
|
});
|
|
54662
54765
|
continue;
|
|
54663
54766
|
}
|
|
54664
|
-
const templatePath =
|
|
54767
|
+
const templatePath = resolve6(config.configDir, outputDef.template);
|
|
54665
54768
|
try {
|
|
54666
54769
|
templateContent = await readFile5(templatePath, "utf8");
|
|
54667
54770
|
} catch {
|
|
@@ -54698,9 +54801,9 @@ async function generateGuardrails(options) {
|
|
|
54698
54801
|
};
|
|
54699
54802
|
const compiled = Handlebars2.compile(templateContent, { noEscape: true });
|
|
54700
54803
|
const output = compiled(groupCtx);
|
|
54701
|
-
const groupTarget =
|
|
54804
|
+
const groupTarget = resolve6(targetPath, groupKey);
|
|
54702
54805
|
if (!dryRun) {
|
|
54703
|
-
await mkdir2(
|
|
54806
|
+
await mkdir2(dirname6(groupTarget), { recursive: true });
|
|
54704
54807
|
await writeFile2(groupTarget, output, "utf8");
|
|
54705
54808
|
if (outputDef.executable) {
|
|
54706
54809
|
await chmod(groupTarget, 493);
|
|
@@ -54712,7 +54815,7 @@ async function generateGuardrails(options) {
|
|
|
54712
54815
|
const compiled = Handlebars2.compile(templateContent, { noEscape: true });
|
|
54713
54816
|
const output = compiled(ctx);
|
|
54714
54817
|
if (!dryRun) {
|
|
54715
|
-
await mkdir2(
|
|
54818
|
+
await mkdir2(dirname6(targetPath), { recursive: true });
|
|
54716
54819
|
await writeFile2(targetPath, output, "utf8");
|
|
54717
54820
|
if (outputDef.executable) {
|
|
54718
54821
|
await chmod(targetPath, 493);
|