@hazeljs/cli 2.0.1 → 2.0.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/cli-manifest.json +86 -1
- package/dist/commands/gatekeeper.d.ts +7 -0
- package/dist/commands/gatekeeper.js +170 -0
- package/dist/index.js +2 -0
- package/dist/utils/packages-registry.js +17 -1
- package/package.json +16 -19
package/cli-manifest.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"description": "Machine-readable manifest of all CLI commands and options for LLM agent tool-use",
|
|
5
5
|
"cli": {
|
|
6
6
|
"name": "hazel",
|
|
7
|
-
"version": "2.0.
|
|
7
|
+
"version": "2.0.2",
|
|
8
8
|
"description": "CLI for generating HazelJS components and applications"
|
|
9
9
|
},
|
|
10
10
|
"commands": [
|
|
@@ -943,6 +943,91 @@
|
|
|
943
943
|
}
|
|
944
944
|
]
|
|
945
945
|
},
|
|
946
|
+
{
|
|
947
|
+
"name": "gatekeeper",
|
|
948
|
+
"usage": "hazel gatekeeper <command>",
|
|
949
|
+
"description": "Agent Gatekeeper — validate, simulate, and explain tool authorization policies (never executes tools)",
|
|
950
|
+
"subcommands": [
|
|
951
|
+
{
|
|
952
|
+
"name": "validate",
|
|
953
|
+
"usage": "hazel gatekeeper validate [--config agent-gatekeeper.yaml] [--json]",
|
|
954
|
+
"description": "Validate an agent-gatekeeper.yaml policy file",
|
|
955
|
+
"options": [
|
|
956
|
+
{
|
|
957
|
+
"name": "config",
|
|
958
|
+
"type": "string",
|
|
959
|
+
"default": "agent-gatekeeper.yaml",
|
|
960
|
+
"description": "Policy config file"
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"name": "json",
|
|
964
|
+
"type": "boolean",
|
|
965
|
+
"description": "Print raw JSON result"
|
|
966
|
+
}
|
|
967
|
+
]
|
|
968
|
+
},
|
|
969
|
+
{
|
|
970
|
+
"name": "simulate",
|
|
971
|
+
"usage": "hazel gatekeeper simulate --agent <id> --tool <name> [--input input.json]",
|
|
972
|
+
"description": "Simulate a gatekeeper decision without executing tools or creating approvals",
|
|
973
|
+
"options": [
|
|
974
|
+
{
|
|
975
|
+
"name": "agent",
|
|
976
|
+
"type": "string",
|
|
977
|
+
"required": true,
|
|
978
|
+
"description": "Agent id"
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
"name": "tool",
|
|
982
|
+
"type": "string",
|
|
983
|
+
"required": true,
|
|
984
|
+
"description": "Tool name"
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
"name": "input",
|
|
988
|
+
"type": "string",
|
|
989
|
+
"description": "JSON input file"
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
"name": "environment",
|
|
993
|
+
"type": "string",
|
|
994
|
+
"default": "development",
|
|
995
|
+
"description": "Environment"
|
|
996
|
+
},
|
|
997
|
+
{
|
|
998
|
+
"name": "tenant",
|
|
999
|
+
"type": "string",
|
|
1000
|
+
"description": "Tenant id"
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
"name": "config",
|
|
1004
|
+
"type": "string",
|
|
1005
|
+
"description": "Optional policy YAML file"
|
|
1006
|
+
}
|
|
1007
|
+
]
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
"name": "explain",
|
|
1011
|
+
"usage": "hazel gatekeeper explain <file> [--config agent-gatekeeper.yaml]",
|
|
1012
|
+
"description": "Explain a saved invocation JSON file (never executes tools)",
|
|
1013
|
+
"args": [
|
|
1014
|
+
{
|
|
1015
|
+
"name": "file",
|
|
1016
|
+
"type": "string",
|
|
1017
|
+
"required": true,
|
|
1018
|
+
"description": "Invocation context JSON file"
|
|
1019
|
+
}
|
|
1020
|
+
],
|
|
1021
|
+
"options": [
|
|
1022
|
+
{
|
|
1023
|
+
"name": "config",
|
|
1024
|
+
"type": "string",
|
|
1025
|
+
"description": "Optional policy YAML file"
|
|
1026
|
+
}
|
|
1027
|
+
]
|
|
1028
|
+
}
|
|
1029
|
+
]
|
|
1030
|
+
},
|
|
946
1031
|
{
|
|
947
1032
|
"name": "install",
|
|
948
1033
|
"usage": "hazel install <spec> [--cwd <dir>] [--registry <dir>]",
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `hazel gatekeeper validate --config agent-gatekeeper.yaml`
|
|
4
|
+
* `hazel gatekeeper simulate --agent refund-agent --tool stripe.refund --input input.json`
|
|
5
|
+
* `hazel gatekeeper explain --invocation invocation.json`
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerGatekeeperCommand(program: Command): void;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerGatekeeperCommand = registerGatekeeperCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* `hazel gatekeeper validate --config agent-gatekeeper.yaml`
|
|
41
|
+
* `hazel gatekeeper simulate --agent refund-agent --tool stripe.refund --input input.json`
|
|
42
|
+
* `hazel gatekeeper explain --invocation invocation.json`
|
|
43
|
+
*/
|
|
44
|
+
function registerGatekeeperCommand(program) {
|
|
45
|
+
const gatekeeper = program
|
|
46
|
+
.command('gatekeeper')
|
|
47
|
+
.description('Agent Gatekeeper — validate, simulate, and explain tool authorization policies');
|
|
48
|
+
gatekeeper
|
|
49
|
+
.command('validate')
|
|
50
|
+
.description('Validate an agent-gatekeeper.yaml policy file')
|
|
51
|
+
.option('--config <file>', 'Policy config file', 'agent-gatekeeper.yaml')
|
|
52
|
+
.option('--json', 'Print raw JSON result')
|
|
53
|
+
.action(async (opts) => {
|
|
54
|
+
try {
|
|
55
|
+
const { loadPoliciesFromFileSync, validatePolicies } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent-gatekeeper')));
|
|
56
|
+
const abs = path.resolve(process.cwd(), opts.config ?? 'agent-gatekeeper.yaml');
|
|
57
|
+
const loaded = loadPoliciesFromFileSync(fs, abs);
|
|
58
|
+
validatePolicies(loaded.policies);
|
|
59
|
+
const result = {
|
|
60
|
+
valid: true,
|
|
61
|
+
config: abs,
|
|
62
|
+
policyCount: loaded.policies.length,
|
|
63
|
+
mode: loaded.mode,
|
|
64
|
+
defaultDecision: loaded.defaultDecision,
|
|
65
|
+
policies: loaded.policies.map((p) => ({
|
|
66
|
+
id: p.id,
|
|
67
|
+
version: p.version,
|
|
68
|
+
priority: p.priority,
|
|
69
|
+
})),
|
|
70
|
+
};
|
|
71
|
+
// eslint-disable-next-line no-console
|
|
72
|
+
console.log(opts.json ? JSON.stringify(result, null, 2) : JSON.stringify(result, null, 2));
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
// eslint-disable-next-line no-console
|
|
76
|
+
console.error(e);
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
gatekeeper
|
|
81
|
+
.command('simulate')
|
|
82
|
+
.description('Simulate gatekeeper decision for an invocation (never executes tools)')
|
|
83
|
+
.requiredOption('--agent <id>', 'Agent id')
|
|
84
|
+
.requiredOption('--tool <name>', 'Tool name')
|
|
85
|
+
.option('--input <file>', 'JSON input file')
|
|
86
|
+
.option('--environment <env>', 'Environment', 'development')
|
|
87
|
+
.option('--tenant <id>', 'Tenant id')
|
|
88
|
+
.option('--config <file>', 'Optional policy YAML file')
|
|
89
|
+
.option('--json', 'Print raw JSON')
|
|
90
|
+
.action(async (opts) => {
|
|
91
|
+
try {
|
|
92
|
+
const { AgentGatekeeper, loadPoliciesFromFileSync, defaultClock, defaultIdGenerator } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent-gatekeeper')));
|
|
93
|
+
let policies = [];
|
|
94
|
+
let mode = 'enforce';
|
|
95
|
+
let defaultDecision = 'deny';
|
|
96
|
+
if (opts.config) {
|
|
97
|
+
const abs = path.resolve(process.cwd(), opts.config);
|
|
98
|
+
const loaded = loadPoliciesFromFileSync(fs, abs);
|
|
99
|
+
policies = loaded.policies;
|
|
100
|
+
mode = loaded.mode ?? mode;
|
|
101
|
+
defaultDecision = loaded.defaultDecision ?? defaultDecision;
|
|
102
|
+
}
|
|
103
|
+
let input = {};
|
|
104
|
+
if (opts.input) {
|
|
105
|
+
const raw = fs.readFileSync(path.resolve(process.cwd(), opts.input), 'utf8');
|
|
106
|
+
input = JSON.parse(raw);
|
|
107
|
+
}
|
|
108
|
+
const gk = new AgentGatekeeper({
|
|
109
|
+
mode,
|
|
110
|
+
defaultDecision,
|
|
111
|
+
policies,
|
|
112
|
+
auditSink: { emit: () => undefined },
|
|
113
|
+
});
|
|
114
|
+
const context = {
|
|
115
|
+
invocationId: defaultIdGenerator()(),
|
|
116
|
+
runId: 'simulate-run',
|
|
117
|
+
agentId: opts.agent,
|
|
118
|
+
tenantId: opts.tenant,
|
|
119
|
+
toolName: opts.tool,
|
|
120
|
+
input,
|
|
121
|
+
environment: opts.environment ?? 'development',
|
|
122
|
+
timestamp: defaultClock().now(),
|
|
123
|
+
};
|
|
124
|
+
const simulation = await gk.simulate(context);
|
|
125
|
+
// eslint-disable-next-line no-console
|
|
126
|
+
console.log(JSON.stringify(simulation, null, 2));
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
// eslint-disable-next-line no-console
|
|
130
|
+
console.error(e);
|
|
131
|
+
process.exitCode = 1;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
gatekeeper
|
|
135
|
+
.command('explain')
|
|
136
|
+
.description('Explain gatekeeper decision from a saved invocation JSON file')
|
|
137
|
+
.argument('<file>', 'Invocation context JSON file')
|
|
138
|
+
.option('--config <file>', 'Optional policy YAML file')
|
|
139
|
+
.option('--json', 'Print raw JSON')
|
|
140
|
+
.action(async (file, opts) => {
|
|
141
|
+
try {
|
|
142
|
+
const { AgentGatekeeper, loadPoliciesFromFileSync, defaultClock } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent-gatekeeper')));
|
|
143
|
+
let policies = [];
|
|
144
|
+
if (opts.config) {
|
|
145
|
+
const abs = path.resolve(process.cwd(), opts.config);
|
|
146
|
+
policies = loadPoliciesFromFileSync(fs, abs).policies;
|
|
147
|
+
}
|
|
148
|
+
const raw = fs.readFileSync(path.resolve(process.cwd(), file), 'utf8');
|
|
149
|
+
const parsed = JSON.parse(raw);
|
|
150
|
+
const context = {
|
|
151
|
+
...parsed,
|
|
152
|
+
timestamp: parsed.timestamp ? new Date(String(parsed.timestamp)) : defaultClock().now(),
|
|
153
|
+
};
|
|
154
|
+
const gk = new AgentGatekeeper({
|
|
155
|
+
mode: 'enforce',
|
|
156
|
+
defaultDecision: 'deny',
|
|
157
|
+
policies,
|
|
158
|
+
auditSink: { emit: () => undefined },
|
|
159
|
+
});
|
|
160
|
+
const simulation = await gk.simulate(context);
|
|
161
|
+
// eslint-disable-next-line no-console
|
|
162
|
+
console.log(JSON.stringify(simulation, null, 2));
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
// eslint-disable-next-line no-console
|
|
166
|
+
console.error(e);
|
|
167
|
+
process.exitCode = 1;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -57,6 +57,7 @@ const eval_1 = require("./commands/eval");
|
|
|
57
57
|
const benchmark_1 = require("./commands/benchmark");
|
|
58
58
|
const agent_1 = require("./commands/agent");
|
|
59
59
|
const skillgate_1 = require("./commands/skillgate");
|
|
60
|
+
const gatekeeper_1 = require("./commands/gatekeeper");
|
|
60
61
|
const store_1 = require("./commands/store");
|
|
61
62
|
// Read version from package.json to ensure consistency
|
|
62
63
|
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json'), 'utf8'));
|
|
@@ -74,6 +75,7 @@ program
|
|
|
74
75
|
(0, benchmark_1.registerBenchmarkCommand)(program);
|
|
75
76
|
(0, agent_1.registerAgentCommand)(program);
|
|
76
77
|
(0, skillgate_1.registerSkillgateCommand)(program);
|
|
78
|
+
(0, gatekeeper_1.registerGatekeeperCommand)(program);
|
|
77
79
|
(0, store_1.registerStoreCommand)(program);
|
|
78
80
|
// Generate command group (unified: hazel g <type> <name> [--path] [--dry-run] [--json], or hazel g --list)
|
|
79
81
|
const generateCommand = program
|
|
@@ -252,7 +252,23 @@ const gate = Skillgate.fromOpenApi(openApiSpec, {
|
|
|
252
252
|
invoke: { baseUrl: process.env.API_BASE_URL || 'http://127.0.0.1:3000' },
|
|
253
253
|
});
|
|
254
254
|
const registry = new ToolRegistry();
|
|
255
|
-
gate.register(registry, 'api-concierge');
|
|
255
|
+
gate.register(registry, 'api-concierge');
|
|
256
|
+
`,
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
shortName: 'agent-gatekeeper',
|
|
260
|
+
npm: '@hazeljs/agent-gatekeeper',
|
|
261
|
+
label: 'Agent Gatekeeper - tool authorization (@hazeljs/agent-gatekeeper)',
|
|
262
|
+
hint: 'import { AgentGatekeeper } from "@hazeljs/agent-gatekeeper";\n // new AgentGatekeeper({ mode: "enforce", defaultDecision: "deny", policies })',
|
|
263
|
+
moduleImport: null,
|
|
264
|
+
moduleExpression: null,
|
|
265
|
+
setupTemplate: `import { AgentGatekeeper } from '@hazeljs/agent-gatekeeper';
|
|
266
|
+
|
|
267
|
+
export const gatekeeper = new AgentGatekeeper({
|
|
268
|
+
mode: 'enforce',
|
|
269
|
+
defaultDecision: 'deny',
|
|
270
|
+
policies: [],
|
|
271
|
+
});
|
|
256
272
|
`,
|
|
257
273
|
},
|
|
258
274
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hazeljs/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Command-line interface for scaffolding and generating HazelJS applications and components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -31,10 +31,11 @@
|
|
|
31
31
|
"mustache": "^4.2.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@hazeljs/eval": "^2.0.
|
|
35
|
-
"@hazeljs/benchmark": "^2.0.
|
|
36
|
-
"@hazeljs/agent": "^2.0.
|
|
37
|
-
"@hazeljs/skillgate": "^2.0.
|
|
34
|
+
"@hazeljs/eval": "^2.0.2",
|
|
35
|
+
"@hazeljs/benchmark": "^2.0.2",
|
|
36
|
+
"@hazeljs/agent": "^2.0.2",
|
|
37
|
+
"@hazeljs/skillgate": "^2.0.2",
|
|
38
|
+
"@hazeljs/agent-gatekeeper": "^2.0.2"
|
|
38
39
|
},
|
|
39
40
|
"peerDependenciesMeta": {
|
|
40
41
|
"@hazeljs/eval": {
|
|
@@ -48,23 +49,19 @@
|
|
|
48
49
|
},
|
|
49
50
|
"@hazeljs/skillgate": {
|
|
50
51
|
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"@hazeljs/agent-gatekeeper": {
|
|
54
|
+
"optional": true
|
|
51
55
|
}
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
54
|
-
"@hazeljs/eval": "^2.0.
|
|
55
|
-
"@hazeljs/benchmark": "^2.0.
|
|
56
|
-
"@hazeljs/agent": "^2.0.
|
|
57
|
-
"@hazeljs/skillgate": "^2.0.
|
|
58
|
-
"@
|
|
59
|
-
"@types/
|
|
60
|
-
"@types/mustache": "^4.2.
|
|
61
|
-
"@types/node": "^20.19.39",
|
|
62
|
-
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
|
63
|
-
"@typescript-eslint/parser": "^8.58.0",
|
|
64
|
-
"eslint": "^8.57.1",
|
|
65
|
-
"jest": "^29.7.0",
|
|
66
|
-
"prettier": "^3.8.1",
|
|
67
|
-
"ts-jest": "^29.4.9",
|
|
58
|
+
"@hazeljs/eval": "^2.0.2",
|
|
59
|
+
"@hazeljs/benchmark": "^2.0.2",
|
|
60
|
+
"@hazeljs/agent": "^2.0.2",
|
|
61
|
+
"@hazeljs/skillgate": "^2.0.2",
|
|
62
|
+
"@hazeljs/agent-gatekeeper": "^2.0.2",
|
|
63
|
+
"@types/inquirer": "^8.2.10",
|
|
64
|
+
"@types/mustache": "^4.2.5",
|
|
68
65
|
"typescript": "^5.9.3"
|
|
69
66
|
},
|
|
70
67
|
"engines": {
|