agent-contracts 0.11.8 → 0.12.1
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 +13 -1
- package/dist/cli.js +242 -33
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +58 -9
- package/dist/index.js +230 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -130,10 +130,21 @@ declare const BindingOutputSchema: z.ZodObject<{
|
|
|
130
130
|
target: z.ZodString;
|
|
131
131
|
template: z.ZodOptional<z.ZodString>;
|
|
132
132
|
inline_template: z.ZodOptional<z.ZodString>;
|
|
133
|
+
source: z.ZodOptional<z.ZodString>;
|
|
133
134
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
134
135
|
write: "write";
|
|
135
136
|
patch: "patch";
|
|
136
137
|
}>>;
|
|
138
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
139
|
+
json: "json";
|
|
140
|
+
yaml: "yaml";
|
|
141
|
+
text: "text";
|
|
142
|
+
}>>;
|
|
143
|
+
patch_strategy: z.ZodOptional<z.ZodEnum<{
|
|
144
|
+
deep_merge: "deep_merge";
|
|
145
|
+
append: "append";
|
|
146
|
+
}>>;
|
|
147
|
+
array_merge_key: z.ZodOptional<z.ZodString>;
|
|
137
148
|
group_by: z.ZodOptional<z.ZodString>;
|
|
138
149
|
executable: z.ZodOptional<z.ZodBoolean>;
|
|
139
150
|
skip_empty: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -172,10 +183,21 @@ declare const SoftwareBindingSchema: z.ZodObject<{
|
|
|
172
183
|
target: z.ZodString;
|
|
173
184
|
template: z.ZodOptional<z.ZodString>;
|
|
174
185
|
inline_template: z.ZodOptional<z.ZodString>;
|
|
186
|
+
source: z.ZodOptional<z.ZodString>;
|
|
175
187
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
176
188
|
write: "write";
|
|
177
189
|
patch: "patch";
|
|
178
190
|
}>>;
|
|
191
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
192
|
+
json: "json";
|
|
193
|
+
yaml: "yaml";
|
|
194
|
+
text: "text";
|
|
195
|
+
}>>;
|
|
196
|
+
patch_strategy: z.ZodOptional<z.ZodEnum<{
|
|
197
|
+
deep_merge: "deep_merge";
|
|
198
|
+
append: "append";
|
|
199
|
+
}>>;
|
|
200
|
+
array_merge_key: z.ZodOptional<z.ZodString>;
|
|
179
201
|
group_by: z.ZodOptional<z.ZodString>;
|
|
180
202
|
executable: z.ZodOptional<z.ZodBoolean>;
|
|
181
203
|
skip_empty: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -1034,8 +1056,18 @@ interface ResolvedConfig {
|
|
|
1034
1056
|
paths?: Record<string, string>;
|
|
1035
1057
|
}
|
|
1036
1058
|
|
|
1037
|
-
|
|
1038
|
-
|
|
1059
|
+
interface LoadedBinding {
|
|
1060
|
+
filePath: string;
|
|
1061
|
+
binding: SoftwareBinding;
|
|
1062
|
+
}
|
|
1063
|
+
declare function loadBindings(bindingPaths: string[]): Promise<LoadedBinding[]>;
|
|
1064
|
+
|
|
1065
|
+
interface RenderOptions {
|
|
1066
|
+
loadedBindings?: LoadedBinding[];
|
|
1067
|
+
activeGuardrailPolicy?: string;
|
|
1068
|
+
}
|
|
1069
|
+
declare function renderFromConfig(dsl: Dsl, renderTargets: ResolvedRenderTarget[], options?: RenderOptions): Promise<string[]>;
|
|
1070
|
+
declare function checkDriftFromConfig(dsl: Dsl, renderTargets: ResolvedRenderTarget[], options?: RenderOptions): Promise<{
|
|
1039
1071
|
hasDrift: boolean;
|
|
1040
1072
|
diffs: string[];
|
|
1041
1073
|
}>;
|
|
@@ -1054,9 +1086,29 @@ interface GlobalContext {
|
|
|
1054
1086
|
guardrail_policies: Dsl["guardrail_policies"];
|
|
1055
1087
|
[key: string]: unknown;
|
|
1056
1088
|
}
|
|
1089
|
+
interface GuardrailEnforcementEntry {
|
|
1090
|
+
guardrail_id: string;
|
|
1091
|
+
description: string;
|
|
1092
|
+
severity: string;
|
|
1093
|
+
action: string;
|
|
1094
|
+
scoped_agents: string[];
|
|
1095
|
+
scoped_tasks: string[];
|
|
1096
|
+
scoped_workflows: string[];
|
|
1097
|
+
scoped_tools: string[];
|
|
1098
|
+
scoped_artifacts: string[];
|
|
1099
|
+
allow_override: boolean;
|
|
1100
|
+
override_requires: string[];
|
|
1101
|
+
trigger: string | null;
|
|
1102
|
+
escalation: {
|
|
1103
|
+
target: string;
|
|
1104
|
+
condition?: string;
|
|
1105
|
+
} | null;
|
|
1106
|
+
}
|
|
1057
1107
|
interface SystemContext {
|
|
1058
1108
|
system: System;
|
|
1059
1109
|
dsl: Dsl;
|
|
1110
|
+
guardrailEnforcement?: GuardrailEnforcementEntry[];
|
|
1111
|
+
bindings?: SoftwareBinding[];
|
|
1060
1112
|
[key: string]: unknown;
|
|
1061
1113
|
}
|
|
1062
1114
|
interface PerTaskContext {
|
|
@@ -1183,7 +1235,10 @@ interface PerAgentContext {
|
|
|
1183
1235
|
[key: string]: unknown;
|
|
1184
1236
|
}
|
|
1185
1237
|
declare function buildGlobalContext(dsl: Dsl): GlobalContext;
|
|
1186
|
-
declare function buildSystemContext(dsl: Dsl
|
|
1238
|
+
declare function buildSystemContext(dsl: Dsl, options?: {
|
|
1239
|
+
loadedBindings?: LoadedBinding[];
|
|
1240
|
+
activeGuardrailPolicy?: string;
|
|
1241
|
+
}): SystemContext;
|
|
1187
1242
|
declare function buildTaskContext(dsl: Dsl, taskId: string): PerTaskContext;
|
|
1188
1243
|
declare function buildArtifactContext(dsl: Dsl, artifactId: string): PerArtifactContext;
|
|
1189
1244
|
declare function buildToolContext(dsl: Dsl, toolId: string): PerToolContext;
|
|
@@ -1197,12 +1252,6 @@ declare function buildPerAgentContext(dsl: Dsl, agent: Agent & {
|
|
|
1197
1252
|
id: string;
|
|
1198
1253
|
}): PerAgentContext;
|
|
1199
1254
|
|
|
1200
|
-
interface LoadedBinding {
|
|
1201
|
-
filePath: string;
|
|
1202
|
-
binding: SoftwareBinding;
|
|
1203
|
-
}
|
|
1204
|
-
declare function loadBindings(bindingPaths: string[]): Promise<LoadedBinding[]>;
|
|
1205
|
-
|
|
1206
1255
|
declare class ConfigLoadError extends Error {
|
|
1207
1256
|
readonly filePath?: string | undefined;
|
|
1208
1257
|
constructor(message: string, filePath?: string | undefined);
|
package/dist/index.js
CHANGED
|
@@ -2242,7 +2242,7 @@ var require_lodash = __commonJS({
|
|
|
2242
2242
|
} else {
|
|
2243
2243
|
newValue = [];
|
|
2244
2244
|
}
|
|
2245
|
-
} else if (
|
|
2245
|
+
} else if (isPlainObject2(srcValue) || isArguments(srcValue)) {
|
|
2246
2246
|
newValue = objValue;
|
|
2247
2247
|
if (isArguments(objValue)) {
|
|
2248
2248
|
newValue = toPlainObject(objValue);
|
|
@@ -3206,7 +3206,7 @@ var require_lodash = __commonJS({
|
|
|
3206
3206
|
return objValue;
|
|
3207
3207
|
}
|
|
3208
3208
|
function customOmitClone(value) {
|
|
3209
|
-
return
|
|
3209
|
+
return isPlainObject2(value) ? undefined2 : value;
|
|
3210
3210
|
}
|
|
3211
3211
|
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
|
|
3212
3212
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length;
|
|
@@ -4707,7 +4707,7 @@ var require_lodash = __commonJS({
|
|
|
4707
4707
|
var isBuffer = nativeIsBuffer || stubFalse;
|
|
4708
4708
|
var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
|
|
4709
4709
|
function isElement(value) {
|
|
4710
|
-
return isObjectLike(value) && value.nodeType === 1 && !
|
|
4710
|
+
return isObjectLike(value) && value.nodeType === 1 && !isPlainObject2(value);
|
|
4711
4711
|
}
|
|
4712
4712
|
function isEmpty(value) {
|
|
4713
4713
|
if (value == null) {
|
|
@@ -4743,7 +4743,7 @@ var require_lodash = __commonJS({
|
|
|
4743
4743
|
return false;
|
|
4744
4744
|
}
|
|
4745
4745
|
var tag = baseGetTag(value);
|
|
4746
|
-
return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !
|
|
4746
|
+
return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject2(value);
|
|
4747
4747
|
}
|
|
4748
4748
|
function isFinite2(value) {
|
|
4749
4749
|
return typeof value == "number" && nativeIsFinite(value);
|
|
@@ -4794,7 +4794,7 @@ var require_lodash = __commonJS({
|
|
|
4794
4794
|
function isNumber(value) {
|
|
4795
4795
|
return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag;
|
|
4796
4796
|
}
|
|
4797
|
-
function
|
|
4797
|
+
function isPlainObject2(value) {
|
|
4798
4798
|
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
|
|
4799
4799
|
return false;
|
|
4800
4800
|
}
|
|
@@ -5865,7 +5865,7 @@ var require_lodash = __commonJS({
|
|
|
5865
5865
|
lodash.isNumber = isNumber;
|
|
5866
5866
|
lodash.isObject = isObject2;
|
|
5867
5867
|
lodash.isObjectLike = isObjectLike;
|
|
5868
|
-
lodash.isPlainObject =
|
|
5868
|
+
lodash.isPlainObject = isPlainObject2;
|
|
5869
5869
|
lodash.isRegExp = isRegExp;
|
|
5870
5870
|
lodash.isSafeInteger = isSafeInteger;
|
|
5871
5871
|
lodash.isSet = isSet;
|
|
@@ -17505,10 +17505,10 @@ var require_immer_cjs_development = __commonJS({
|
|
|
17505
17505
|
function isDraftable(value) {
|
|
17506
17506
|
var _value$constructor;
|
|
17507
17507
|
if (!value) return false;
|
|
17508
|
-
return
|
|
17508
|
+
return isPlainObject2(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!((_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor[DRAFTABLE]) || isMap(value) || isSet(value);
|
|
17509
17509
|
}
|
|
17510
17510
|
var objectCtorString = /* @__PURE__ */ Object.prototype.constructor.toString();
|
|
17511
|
-
function
|
|
17511
|
+
function isPlainObject2(value) {
|
|
17512
17512
|
if (!value || typeof value !== "object") return false;
|
|
17513
17513
|
var proto = Object.getPrototypeOf(value);
|
|
17514
17514
|
if (proto === null) {
|
|
@@ -40191,10 +40191,10 @@ var require_object_inspect = __commonJS({
|
|
|
40191
40191
|
}
|
|
40192
40192
|
if (!isDate(obj) && !isRegExp(obj)) {
|
|
40193
40193
|
var ys = arrObjKeys(obj, inspect);
|
|
40194
|
-
var
|
|
40194
|
+
var isPlainObject2 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
|
|
40195
40195
|
var protoTag = obj instanceof Object ? "" : "null prototype";
|
|
40196
|
-
var stringTag = !
|
|
40197
|
-
var constructorTag =
|
|
40196
|
+
var stringTag = !isPlainObject2 && toStringTag2 && Object(obj) === obj && toStringTag2 in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
|
|
40197
|
+
var constructorTag = isPlainObject2 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
|
|
40198
40198
|
var tag = constructorTag + (stringTag || protoTag ? "[" + $join.call($concat.call([], stringTag || [], protoTag || []), ": ") + "] " : "");
|
|
40199
40199
|
if (ys.length === 0) {
|
|
40200
40200
|
return tag + "{}";
|
|
@@ -44529,7 +44529,7 @@ var require_lodash3 = __commonJS({
|
|
|
44529
44529
|
} else {
|
|
44530
44530
|
newValue = [];
|
|
44531
44531
|
}
|
|
44532
|
-
} else if (
|
|
44532
|
+
} else if (isPlainObject2(srcValue) || isArguments(srcValue)) {
|
|
44533
44533
|
newValue = objValue;
|
|
44534
44534
|
if (isArguments(objValue)) {
|
|
44535
44535
|
newValue = toPlainObject(objValue);
|
|
@@ -45500,7 +45500,7 @@ var require_lodash3 = __commonJS({
|
|
|
45500
45500
|
return objValue;
|
|
45501
45501
|
}
|
|
45502
45502
|
function customOmitClone(value) {
|
|
45503
|
-
return
|
|
45503
|
+
return isPlainObject2(value) ? undefined2 : value;
|
|
45504
45504
|
}
|
|
45505
45505
|
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
|
|
45506
45506
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length;
|
|
@@ -47001,7 +47001,7 @@ var require_lodash3 = __commonJS({
|
|
|
47001
47001
|
var isBuffer = nativeIsBuffer || stubFalse;
|
|
47002
47002
|
var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
|
|
47003
47003
|
function isElement(value) {
|
|
47004
|
-
return isObjectLike(value) && value.nodeType === 1 && !
|
|
47004
|
+
return isObjectLike(value) && value.nodeType === 1 && !isPlainObject2(value);
|
|
47005
47005
|
}
|
|
47006
47006
|
function isEmpty(value) {
|
|
47007
47007
|
if (value == null) {
|
|
@@ -47037,7 +47037,7 @@ var require_lodash3 = __commonJS({
|
|
|
47037
47037
|
return false;
|
|
47038
47038
|
}
|
|
47039
47039
|
var tag = baseGetTag(value);
|
|
47040
|
-
return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !
|
|
47040
|
+
return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject2(value);
|
|
47041
47041
|
}
|
|
47042
47042
|
function isFinite2(value) {
|
|
47043
47043
|
return typeof value == "number" && nativeIsFinite(value);
|
|
@@ -47088,7 +47088,7 @@ var require_lodash3 = __commonJS({
|
|
|
47088
47088
|
function isNumber(value) {
|
|
47089
47089
|
return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag;
|
|
47090
47090
|
}
|
|
47091
|
-
function
|
|
47091
|
+
function isPlainObject2(value) {
|
|
47092
47092
|
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
|
|
47093
47093
|
return false;
|
|
47094
47094
|
}
|
|
@@ -48154,7 +48154,7 @@ var require_lodash3 = __commonJS({
|
|
|
48154
48154
|
lodash.isNumber = isNumber;
|
|
48155
48155
|
lodash.isObject = isObject2;
|
|
48156
48156
|
lodash.isObjectLike = isObjectLike;
|
|
48157
|
-
lodash.isPlainObject =
|
|
48157
|
+
lodash.isPlainObject = isPlainObject2;
|
|
48158
48158
|
lodash.isRegExp = isRegExp;
|
|
48159
48159
|
lodash.isSafeInteger = isSafeInteger;
|
|
48160
48160
|
lodash.isSet = isSet;
|
|
@@ -50511,13 +50511,20 @@ var BindingOutputSchema = z3.object({
|
|
|
50511
50511
|
target: z3.string(),
|
|
50512
50512
|
template: z3.string().optional(),
|
|
50513
50513
|
inline_template: z3.string().optional(),
|
|
50514
|
+
source: z3.string().optional(),
|
|
50514
50515
|
mode: z3.enum(["write", "patch"]).default("write"),
|
|
50516
|
+
format: z3.enum(["json", "yaml", "text"]).optional(),
|
|
50517
|
+
patch_strategy: z3.enum(["deep_merge", "append"]).optional(),
|
|
50518
|
+
array_merge_key: z3.string().optional(),
|
|
50515
50519
|
group_by: z3.string().optional(),
|
|
50516
50520
|
executable: z3.boolean().optional(),
|
|
50517
50521
|
skip_empty: z3.boolean().optional()
|
|
50518
50522
|
}).passthrough().refine(
|
|
50519
|
-
(data) =>
|
|
50520
|
-
|
|
50523
|
+
(data) => {
|
|
50524
|
+
const count = [data.template, data.inline_template, data.source].filter(Boolean).length;
|
|
50525
|
+
return count === 1 || count === 0;
|
|
50526
|
+
},
|
|
50527
|
+
{ message: "Only one of template, inline_template, or source may be specified" }
|
|
50521
50528
|
);
|
|
50522
50529
|
var ReportingSchema = z3.object({
|
|
50523
50530
|
commands: z3.record(z3.string(), z3.string()),
|
|
@@ -53129,8 +53136,52 @@ function buildGlobalContext(dsl) {
|
|
|
53129
53136
|
guardrail_policies: dsl.guardrail_policies
|
|
53130
53137
|
};
|
|
53131
53138
|
}
|
|
53132
|
-
function buildSystemContext(dsl) {
|
|
53133
|
-
|
|
53139
|
+
function buildSystemContext(dsl, options) {
|
|
53140
|
+
const ctx = { system: dsl.system, dsl };
|
|
53141
|
+
if (options?.loadedBindings && options.loadedBindings.length > 0) {
|
|
53142
|
+
ctx.bindings = options.loadedBindings.map((lb) => lb.binding);
|
|
53143
|
+
const policyName = options.activeGuardrailPolicy;
|
|
53144
|
+
const policy = policyName ? dsl.guardrail_policies[policyName] : void 0;
|
|
53145
|
+
if (policy) {
|
|
53146
|
+
ctx.guardrailEnforcement = buildGuardrailEnforcement(dsl, policy, options.loadedBindings);
|
|
53147
|
+
}
|
|
53148
|
+
}
|
|
53149
|
+
return ctx;
|
|
53150
|
+
}
|
|
53151
|
+
function buildGuardrailEnforcement(dsl, policy, loadedBindings) {
|
|
53152
|
+
const entries = [];
|
|
53153
|
+
const bindingTriggers = /* @__PURE__ */ new Map();
|
|
53154
|
+
for (const lb of loadedBindings) {
|
|
53155
|
+
const impl = lb.binding.guardrail_impl ?? {};
|
|
53156
|
+
for (const [guardrailId, gi] of Object.entries(impl)) {
|
|
53157
|
+
for (const check of gi.checks) {
|
|
53158
|
+
if (check.matcher) {
|
|
53159
|
+
bindingTriggers.set(guardrailId, check.matcher.type);
|
|
53160
|
+
}
|
|
53161
|
+
}
|
|
53162
|
+
}
|
|
53163
|
+
}
|
|
53164
|
+
for (const rule of policy.rules) {
|
|
53165
|
+
const guardrail = dsl.guardrails[rule.guardrail];
|
|
53166
|
+
if (!guardrail) continue;
|
|
53167
|
+
const scope = guardrail.scope ?? {};
|
|
53168
|
+
entries.push({
|
|
53169
|
+
guardrail_id: rule.guardrail,
|
|
53170
|
+
description: guardrail.description,
|
|
53171
|
+
severity: rule.severity,
|
|
53172
|
+
action: rule.action,
|
|
53173
|
+
scoped_agents: scope.agents ?? [],
|
|
53174
|
+
scoped_tasks: scope.tasks ?? [],
|
|
53175
|
+
scoped_workflows: scope.workflows ?? [],
|
|
53176
|
+
scoped_tools: scope.tools ?? [],
|
|
53177
|
+
scoped_artifacts: scope.artifacts ?? [],
|
|
53178
|
+
allow_override: rule.allow_override,
|
|
53179
|
+
override_requires: rule.override_requires ?? [],
|
|
53180
|
+
trigger: bindingTriggers.get(rule.guardrail) ?? null,
|
|
53181
|
+
escalation: rule.escalation ? { target: rule.escalation.target, condition: rule.escalation.condition } : null
|
|
53182
|
+
});
|
|
53183
|
+
}
|
|
53184
|
+
return entries;
|
|
53134
53185
|
}
|
|
53135
53186
|
function buildTaskContext(dsl, taskId) {
|
|
53136
53187
|
const taskDef = dsl.tasks[taskId];
|
|
@@ -54185,6 +54236,50 @@ Handlebars.registerHelper(
|
|
|
54185
54236
|
return generateOverviewFlowchart(dsl);
|
|
54186
54237
|
}
|
|
54187
54238
|
);
|
|
54239
|
+
Handlebars.registerHelper(
|
|
54240
|
+
"guardrailCoverageMatrix",
|
|
54241
|
+
function() {
|
|
54242
|
+
const enforcement = this["guardrailEnforcement"];
|
|
54243
|
+
if (!enforcement || enforcement.length === 0) return "";
|
|
54244
|
+
const header = "| Guardrail | Severity | Action | Agents | Tasks | Workflows | Tools | Artifacts | Trigger | Override | Escalation |";
|
|
54245
|
+
const divider = "|-----------|----------|--------|--------|-------|-----------|-------|-----------|---------|----------|------------|";
|
|
54246
|
+
const rows = enforcement.map((e3) => {
|
|
54247
|
+
const agents = e3["scoped_agents"]?.join(", ") || "\u2014";
|
|
54248
|
+
const tasks = e3["scoped_tasks"]?.join(", ") || "\u2014";
|
|
54249
|
+
const workflows = e3["scoped_workflows"]?.join(", ") || "\u2014";
|
|
54250
|
+
const tools = e3["scoped_tools"]?.join(", ") || "\u2014";
|
|
54251
|
+
const artifacts = e3["scoped_artifacts"]?.join(", ") || "\u2014";
|
|
54252
|
+
const trigger = e3["trigger"] || "\u2014";
|
|
54253
|
+
const override = e3["allow_override"] ? "yes" : "no";
|
|
54254
|
+
const esc = e3["escalation"];
|
|
54255
|
+
const escalation = esc ? esc["target"] : "\u2014";
|
|
54256
|
+
return `| ${e3["guardrail_id"]} | ${e3["severity"]} | ${e3["action"]} | ${agents} | ${tasks} | ${workflows} | ${tools} | ${artifacts} | ${trigger} | ${override} | ${escalation} |`;
|
|
54257
|
+
});
|
|
54258
|
+
return [header, divider, ...rows].join("\n");
|
|
54259
|
+
}
|
|
54260
|
+
);
|
|
54261
|
+
Handlebars.registerHelper(
|
|
54262
|
+
"taskGuardrailMatrix",
|
|
54263
|
+
function() {
|
|
54264
|
+
const dsl = this["dsl"];
|
|
54265
|
+
const enforcement = this["guardrailEnforcement"];
|
|
54266
|
+
if (!dsl || !enforcement || enforcement.length === 0) return "";
|
|
54267
|
+
const taskIds = Object.keys(dsl.tasks);
|
|
54268
|
+
if (taskIds.length === 0) return "";
|
|
54269
|
+
const guardrailIds = enforcement.map((e3) => e3["guardrail_id"]);
|
|
54270
|
+
const header = `| Task | ${guardrailIds.join(" | ")} |`;
|
|
54271
|
+
const divider = `|------|${guardrailIds.map(() => "------").join("|")}|`;
|
|
54272
|
+
const rows = taskIds.map((taskId) => {
|
|
54273
|
+
const cells = enforcement.map((e3) => {
|
|
54274
|
+
const scopedTasks = e3["scoped_tasks"];
|
|
54275
|
+
if (scopedTasks.length > 0 && !scopedTasks.includes(taskId)) return "n/a";
|
|
54276
|
+
return e3["action"];
|
|
54277
|
+
});
|
|
54278
|
+
return `| ${taskId} | ${cells.join(" | ")} |`;
|
|
54279
|
+
});
|
|
54280
|
+
return [header, divider, ...rows].join("\n");
|
|
54281
|
+
}
|
|
54282
|
+
);
|
|
54188
54283
|
function getDslSection(dsl, context) {
|
|
54189
54284
|
const sectionMap = {
|
|
54190
54285
|
agent: dsl.agents,
|
|
@@ -54249,13 +54344,13 @@ async function removeIfExists(filePath) {
|
|
|
54249
54344
|
} catch {
|
|
54250
54345
|
}
|
|
54251
54346
|
}
|
|
54252
|
-
async function renderFromConfig(dsl, renderTargets) {
|
|
54347
|
+
async function renderFromConfig(dsl, renderTargets, options) {
|
|
54253
54348
|
const outputFiles = [];
|
|
54254
54349
|
for (const target of renderTargets) {
|
|
54255
54350
|
const templateContent = await loadTemplate(target.template);
|
|
54256
54351
|
const compiled = Handlebars.compile(templateContent, { noEscape: false });
|
|
54257
54352
|
if (target.context === "system") {
|
|
54258
|
-
const ctx = buildSystemContext(dsl);
|
|
54353
|
+
const ctx = buildSystemContext(dsl, options);
|
|
54259
54354
|
const output = compiled(ctx);
|
|
54260
54355
|
if (target.skip_empty && isEffectivelyEmpty(output)) {
|
|
54261
54356
|
await removeIfExists(target.output);
|
|
@@ -54304,13 +54399,13 @@ function checkExpectedVsExisting(expected, outputPath, skipEmpty, diffs) {
|
|
|
54304
54399
|
diffs.push(outputPath);
|
|
54305
54400
|
});
|
|
54306
54401
|
}
|
|
54307
|
-
async function checkDriftFromConfig(dsl, renderTargets) {
|
|
54402
|
+
async function checkDriftFromConfig(dsl, renderTargets, options) {
|
|
54308
54403
|
const diffs = [];
|
|
54309
54404
|
for (const target of renderTargets) {
|
|
54310
54405
|
const templateContent = await loadTemplate(target.template);
|
|
54311
54406
|
const compiled = Handlebars.compile(templateContent, { noEscape: false });
|
|
54312
54407
|
if (target.context === "system") {
|
|
54313
|
-
const ctx = buildSystemContext(dsl);
|
|
54408
|
+
const ctx = buildSystemContext(dsl, options);
|
|
54314
54409
|
const expected = compiled(ctx);
|
|
54315
54410
|
await checkExpectedVsExisting(expected, target.output, target.skip_empty, diffs);
|
|
54316
54411
|
} else {
|
|
@@ -54873,9 +54968,10 @@ function score(dsl) {
|
|
|
54873
54968
|
}
|
|
54874
54969
|
|
|
54875
54970
|
// src/guardrail-generator/generator.ts
|
|
54876
|
-
import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod, unlink as unlink2 } from "fs/promises";
|
|
54971
|
+
import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod, unlink as unlink2, copyFile } from "fs/promises";
|
|
54877
54972
|
import { resolve as resolve6, dirname as dirname6 } from "path";
|
|
54878
54973
|
import Handlebars2 from "handlebars";
|
|
54974
|
+
import YAML from "yaml";
|
|
54879
54975
|
|
|
54880
54976
|
// src/guardrail-generator/resolve-checks.ts
|
|
54881
54977
|
function resolveChecks(dsl, binding, policy) {
|
|
@@ -54947,6 +55043,81 @@ Handlebars2.registerHelper(
|
|
|
54947
55043
|
return new Handlebars2.SafeString(result);
|
|
54948
55044
|
}
|
|
54949
55045
|
);
|
|
55046
|
+
function isPlainObject(val) {
|
|
55047
|
+
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
55048
|
+
}
|
|
55049
|
+
function deepMergeArrays(existing, incoming, mergeKey) {
|
|
55050
|
+
if (!mergeKey) return [...existing, ...incoming];
|
|
55051
|
+
const merged = [...existing];
|
|
55052
|
+
for (const item of incoming) {
|
|
55053
|
+
if (isPlainObject(item) && mergeKey in item) {
|
|
55054
|
+
const idx = merged.findIndex(
|
|
55055
|
+
(e3) => isPlainObject(e3) && e3[mergeKey] === item[mergeKey]
|
|
55056
|
+
);
|
|
55057
|
+
if (idx >= 0) {
|
|
55058
|
+
merged[idx] = item;
|
|
55059
|
+
} else {
|
|
55060
|
+
merged.push(item);
|
|
55061
|
+
}
|
|
55062
|
+
} else {
|
|
55063
|
+
merged.push(item);
|
|
55064
|
+
}
|
|
55065
|
+
}
|
|
55066
|
+
return merged;
|
|
55067
|
+
}
|
|
55068
|
+
function deepMerge(existing, incoming, arrayMergeKey) {
|
|
55069
|
+
if (Array.isArray(existing) && Array.isArray(incoming)) {
|
|
55070
|
+
return deepMergeArrays(existing, incoming, arrayMergeKey);
|
|
55071
|
+
}
|
|
55072
|
+
if (isPlainObject(existing) && isPlainObject(incoming)) {
|
|
55073
|
+
const result = { ...existing };
|
|
55074
|
+
for (const [key, val] of Object.entries(incoming)) {
|
|
55075
|
+
result[key] = key in result ? deepMerge(result[key], val, arrayMergeKey) : val;
|
|
55076
|
+
}
|
|
55077
|
+
return result;
|
|
55078
|
+
}
|
|
55079
|
+
return incoming;
|
|
55080
|
+
}
|
|
55081
|
+
function parseContent(raw, format2) {
|
|
55082
|
+
if (format2 === "json") return JSON.parse(raw);
|
|
55083
|
+
if (format2 === "yaml") return YAML.parse(raw);
|
|
55084
|
+
throw new Error(`Unsupported format for patch parsing: ${format2}`);
|
|
55085
|
+
}
|
|
55086
|
+
function serializeContent(data, format2) {
|
|
55087
|
+
if (format2 === "json") return JSON.stringify(data, null, 2) + "\n";
|
|
55088
|
+
if (format2 === "yaml") return YAML.stringify(data);
|
|
55089
|
+
throw new Error(`Unsupported format for patch serialization: ${format2}`);
|
|
55090
|
+
}
|
|
55091
|
+
async function applyPatch(targetPath, patchContent, outputDef) {
|
|
55092
|
+
const format2 = outputDef.format ?? "json";
|
|
55093
|
+
if (format2 === "text") {
|
|
55094
|
+
let existing = "";
|
|
55095
|
+
try {
|
|
55096
|
+
existing = await readFile5(targetPath, "utf8");
|
|
55097
|
+
} catch {
|
|
55098
|
+
}
|
|
55099
|
+
return existing + patchContent;
|
|
55100
|
+
}
|
|
55101
|
+
const patchData = parseContent(patchContent, format2);
|
|
55102
|
+
let existingData;
|
|
55103
|
+
try {
|
|
55104
|
+
const existingRaw = await readFile5(targetPath, "utf8");
|
|
55105
|
+
existingData = parseContent(existingRaw, format2);
|
|
55106
|
+
} catch {
|
|
55107
|
+
return serializeContent(patchData, format2);
|
|
55108
|
+
}
|
|
55109
|
+
const strategy = outputDef.patch_strategy ?? "deep_merge";
|
|
55110
|
+
if (strategy === "append" && Array.isArray(existingData)) {
|
|
55111
|
+
const merged2 = deepMergeArrays(
|
|
55112
|
+
existingData,
|
|
55113
|
+
Array.isArray(patchData) ? patchData : [patchData],
|
|
55114
|
+
outputDef.array_merge_key
|
|
55115
|
+
);
|
|
55116
|
+
return serializeContent(merged2, format2);
|
|
55117
|
+
}
|
|
55118
|
+
const merged = deepMerge(existingData, patchData, outputDef.array_merge_key);
|
|
55119
|
+
return serializeContent(merged, format2);
|
|
55120
|
+
}
|
|
54950
55121
|
async function generateGuardrails(options) {
|
|
54951
55122
|
const { dsl, config, loadedBindings, filterBindings, dryRun } = options;
|
|
54952
55123
|
const outputFiles = [];
|
|
@@ -55016,6 +55187,31 @@ async function generateGuardrails(options) {
|
|
|
55016
55187
|
continue;
|
|
55017
55188
|
}
|
|
55018
55189
|
const targetPath = resolve6(config.configDir, pathResult.resolved);
|
|
55190
|
+
if (outputDef.source) {
|
|
55191
|
+
const sourcePath = resolve6(config.configDir, outputDef.source);
|
|
55192
|
+
if (!dryRun) {
|
|
55193
|
+
try {
|
|
55194
|
+
await mkdir2(dirname6(targetPath), { recursive: true });
|
|
55195
|
+
await copyFile(sourcePath, targetPath);
|
|
55196
|
+
if (outputDef.executable) {
|
|
55197
|
+
await chmod(targetPath, 493);
|
|
55198
|
+
}
|
|
55199
|
+
} catch (err) {
|
|
55200
|
+
const code = err.code;
|
|
55201
|
+
if (code === "ENOENT") {
|
|
55202
|
+
diagnostics.push({
|
|
55203
|
+
path: `binding.${binding.software}.outputs.${outputId}`,
|
|
55204
|
+
message: `Source file not found: ${sourcePath}`,
|
|
55205
|
+
severity: "error"
|
|
55206
|
+
});
|
|
55207
|
+
continue;
|
|
55208
|
+
}
|
|
55209
|
+
throw err;
|
|
55210
|
+
}
|
|
55211
|
+
}
|
|
55212
|
+
outputFiles.push(targetPath);
|
|
55213
|
+
continue;
|
|
55214
|
+
}
|
|
55019
55215
|
let templateContent;
|
|
55020
55216
|
if (outputDef.inline_template) {
|
|
55021
55217
|
templateContent = outputDef.inline_template;
|
|
@@ -55042,12 +55238,13 @@ async function generateGuardrails(options) {
|
|
|
55042
55238
|
} else {
|
|
55043
55239
|
diagnostics.push({
|
|
55044
55240
|
path: `binding.${binding.software}.outputs.${outputId}`,
|
|
55045
|
-
message: "Output has neither template nor
|
|
55241
|
+
message: "Output has neither template, inline_template, nor source",
|
|
55046
55242
|
severity: "error"
|
|
55047
55243
|
});
|
|
55048
55244
|
continue;
|
|
55049
55245
|
}
|
|
55050
55246
|
const shouldSkipEmpty = outputDef.skip_empty === true;
|
|
55247
|
+
const isPatch = outputDef.mode === "patch";
|
|
55051
55248
|
if (outputDef.group_by) {
|
|
55052
55249
|
const groupField = outputDef.group_by;
|
|
55053
55250
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -55065,9 +55262,9 @@ async function generateGuardrails(options) {
|
|
|
55065
55262
|
current_group: groupKey
|
|
55066
55263
|
};
|
|
55067
55264
|
const compiled = Handlebars2.compile(templateContent, { noEscape: true });
|
|
55068
|
-
const
|
|
55265
|
+
const rendered = compiled(groupCtx);
|
|
55069
55266
|
const groupTarget = resolve6(targetPath, groupKey);
|
|
55070
|
-
if (shouldSkipEmpty &&
|
|
55267
|
+
if (shouldSkipEmpty && rendered.trim().length === 0) {
|
|
55071
55268
|
if (!dryRun) {
|
|
55072
55269
|
try {
|
|
55073
55270
|
await unlink2(groupTarget);
|
|
@@ -55076,6 +55273,7 @@ async function generateGuardrails(options) {
|
|
|
55076
55273
|
}
|
|
55077
55274
|
continue;
|
|
55078
55275
|
}
|
|
55276
|
+
const output = isPatch && !dryRun ? await applyPatch(groupTarget, rendered, outputDef) : rendered;
|
|
55079
55277
|
if (!dryRun) {
|
|
55080
55278
|
await mkdir2(dirname6(groupTarget), { recursive: true });
|
|
55081
55279
|
await writeFile2(groupTarget, output, "utf8");
|
|
@@ -55087,8 +55285,8 @@ async function generateGuardrails(options) {
|
|
|
55087
55285
|
}
|
|
55088
55286
|
} else {
|
|
55089
55287
|
const compiled = Handlebars2.compile(templateContent, { noEscape: true });
|
|
55090
|
-
const
|
|
55091
|
-
if (shouldSkipEmpty &&
|
|
55288
|
+
const rendered = compiled(ctx);
|
|
55289
|
+
if (shouldSkipEmpty && rendered.trim().length === 0) {
|
|
55092
55290
|
if (!dryRun) {
|
|
55093
55291
|
try {
|
|
55094
55292
|
await unlink2(targetPath);
|
|
@@ -55096,6 +55294,7 @@ async function generateGuardrails(options) {
|
|
|
55096
55294
|
}
|
|
55097
55295
|
}
|
|
55098
55296
|
} else {
|
|
55297
|
+
const output = isPatch && !dryRun ? await applyPatch(targetPath, rendered, outputDef) : rendered;
|
|
55099
55298
|
if (!dryRun) {
|
|
55100
55299
|
await mkdir2(dirname6(targetPath), { recursive: true });
|
|
55101
55300
|
await writeFile2(targetPath, output, "utf8");
|