@hazeljs/cli 1.0.6 → 2.0.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/@template-ai-native/README.md +19 -0
- package/@template-ai-native/src/examples/skillgate.example.ts +29 -0
- package/cli-manifest.json +82 -1
- package/dist/commands/agent-templates.d.ts +27 -0
- package/dist/commands/agent-templates.js +480 -0
- package/dist/commands/agent.d.ts +5 -1
- package/dist/commands/agent.js +723 -3
- package/dist/commands/agent.test.d.ts +1 -0
- package/dist/commands/agent.test.js +104 -0
- package/dist/commands/skillgate.d.ts +6 -0
- package/dist/commands/skillgate.js +147 -0
- package/dist/commands/store.d.ts +7 -0
- package/dist/commands/store.js +203 -0
- package/dist/commands/store.test.d.ts +1 -0
- package/dist/commands/store.test.js +120 -0
- package/dist/index.js +4 -0
- package/dist/utils/packages-registry.js +19 -0
- package/package.json +12 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
const fs = __importStar(require("fs"));
|
|
37
|
+
const os = __importStar(require("os"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const commander_1 = require("commander");
|
|
40
|
+
const agent_1 = require("./agent");
|
|
41
|
+
const agent_templates_1 = require("./agent-templates");
|
|
42
|
+
describe('registerAgentCommand (AOS-011 + templates)', () => {
|
|
43
|
+
it('registers run, logs, doctor, new, and templates subcommands', () => {
|
|
44
|
+
const program = new commander_1.Command();
|
|
45
|
+
(0, agent_1.registerAgentCommand)(program);
|
|
46
|
+
const agent = program.commands.find((c) => c.name() === 'agent');
|
|
47
|
+
expect(agent).toBeDefined();
|
|
48
|
+
const names = agent.commands.map((c) => c.name());
|
|
49
|
+
expect(names).toEqual(expect.arrayContaining([
|
|
50
|
+
'install',
|
|
51
|
+
'dna',
|
|
52
|
+
'run',
|
|
53
|
+
'logs',
|
|
54
|
+
'doctor',
|
|
55
|
+
'runs',
|
|
56
|
+
'new',
|
|
57
|
+
'templates',
|
|
58
|
+
'apply',
|
|
59
|
+
'get',
|
|
60
|
+
'describe',
|
|
61
|
+
'delete',
|
|
62
|
+
'events',
|
|
63
|
+
]));
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('agent templates scaffold', () => {
|
|
67
|
+
let tmp;
|
|
68
|
+
beforeEach(() => {
|
|
69
|
+
tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'hazel-agent-new-'));
|
|
70
|
+
});
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
73
|
+
});
|
|
74
|
+
it('lists three templates', () => {
|
|
75
|
+
expect((0, agent_templates_1.listAgentTemplates)().map((t) => t.id)).toEqual(['bare', 'agent-os', 'skillgate']);
|
|
76
|
+
});
|
|
77
|
+
it('scaffolds bare DNA package', () => {
|
|
78
|
+
const dest = path.join(tmp, 'bare-demo');
|
|
79
|
+
const result = (0, agent_templates_1.scaffoldAgentProject)({ name: 'bare-demo', destDir: dest, template: 'bare' });
|
|
80
|
+
expect(result.files).toContain('dna/agent.marketplace.json');
|
|
81
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dest, 'dna/agent.marketplace.json'), 'utf8'));
|
|
82
|
+
expect(pkg.dna.format).toBe('hazeljs.agent.dna');
|
|
83
|
+
expect(pkg.dna.name).toBeTruthy();
|
|
84
|
+
});
|
|
85
|
+
it('scaffolds agent-os with real tool source', () => {
|
|
86
|
+
const dest = path.join(tmp, 'os-demo');
|
|
87
|
+
(0, agent_templates_1.scaffoldAgentProject)({ name: 'os-demo', destDir: dest, template: 'agent-os' });
|
|
88
|
+
expect(fs.existsSync(path.join(dest, 'src/support.agent.ts'))).toBe(true);
|
|
89
|
+
expect(fs.existsSync(path.join(dest, 'src/main.ts'))).toBe(true);
|
|
90
|
+
expect(fs.existsSync(path.join(dest, 'dna/agent.marketplace.json'))).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
it('scaffolds skillgate with openapi sample', () => {
|
|
93
|
+
const dest = path.join(tmp, 'sg-demo');
|
|
94
|
+
(0, agent_templates_1.scaffoldAgentProject)({ name: 'sg-demo', destDir: dest, template: 'skillgate' });
|
|
95
|
+
expect(fs.existsSync(path.join(dest, 'openapi/sample.openapi.json'))).toBe(true);
|
|
96
|
+
expect(fs.existsSync(path.join(dest, 'src/report.ts'))).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
it('refuses non-empty dest without force', () => {
|
|
99
|
+
const dest = path.join(tmp, 'taken');
|
|
100
|
+
fs.mkdirSync(dest);
|
|
101
|
+
fs.writeFileSync(path.join(dest, 'x.txt'), 'x');
|
|
102
|
+
expect(() => (0, agent_templates_1.scaffoldAgentProject)({ name: 'taken', destDir: dest, template: 'bare' })).toThrow(/not empty/);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `hazel skillgate from-openapi <file>` — preview governed skills from an OpenAPI doc.
|
|
4
|
+
* `hazel skillgate init` — write a starter skillgate.config.json.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerSkillgateCommand(program: Command): void;
|
|
@@ -0,0 +1,147 @@
|
|
|
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.registerSkillgateCommand = registerSkillgateCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* `hazel skillgate from-openapi <file>` — preview governed skills from an OpenAPI doc.
|
|
41
|
+
* `hazel skillgate init` — write a starter skillgate.config.json.
|
|
42
|
+
*/
|
|
43
|
+
function registerSkillgateCommand(program) {
|
|
44
|
+
const skillgate = program
|
|
45
|
+
.command('skillgate')
|
|
46
|
+
.description('Skillgate — OpenAPI → curated, governed agent skills');
|
|
47
|
+
skillgate
|
|
48
|
+
.command('from-openapi')
|
|
49
|
+
.description('Parse an OpenAPI JSON file and print the Skillgate report')
|
|
50
|
+
.argument('<file>', 'Path to OpenAPI JSON')
|
|
51
|
+
.option('--mode <mode>', 'Include mode: opt-in | all', 'opt-in')
|
|
52
|
+
.option('--tags <tags>', 'Comma-separated tag allowlist')
|
|
53
|
+
.option('--allow-destructive', 'Allow DELETE / destructive methods')
|
|
54
|
+
.option('--allow-admin', 'Allow admin / internal paths')
|
|
55
|
+
.option('--base-url <url>', 'Override servers[0].url for invokers')
|
|
56
|
+
.option('--json', 'Print raw JSON report')
|
|
57
|
+
.action(async (file, opts) => {
|
|
58
|
+
try {
|
|
59
|
+
const { Skillgate } = await Promise.resolve().then(() => __importStar(require('@hazeljs/skillgate')));
|
|
60
|
+
const abs = path.resolve(process.cwd(), file);
|
|
61
|
+
const raw = fs.readFileSync(abs, 'utf8');
|
|
62
|
+
const spec = JSON.parse(raw);
|
|
63
|
+
const gate = Skillgate.fromOpenApi(spec, {
|
|
64
|
+
include: {
|
|
65
|
+
mode: opts.mode === 'all' ? 'all' : 'opt-in',
|
|
66
|
+
tags: opts.tags
|
|
67
|
+
? opts.tags
|
|
68
|
+
.split(',')
|
|
69
|
+
.map((t) => t.trim())
|
|
70
|
+
.filter(Boolean)
|
|
71
|
+
: undefined,
|
|
72
|
+
},
|
|
73
|
+
classify: {
|
|
74
|
+
allowDestructive: Boolean(opts.allowDestructive),
|
|
75
|
+
allowAdmin: Boolean(opts.allowAdmin),
|
|
76
|
+
},
|
|
77
|
+
invoke: opts.baseUrl ? { baseUrl: opts.baseUrl } : undefined,
|
|
78
|
+
force: true,
|
|
79
|
+
});
|
|
80
|
+
const report = gate.report();
|
|
81
|
+
if (opts.json) {
|
|
82
|
+
// eslint-disable-next-line no-console
|
|
83
|
+
console.log(JSON.stringify(report, null, 2));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// eslint-disable-next-line no-console
|
|
87
|
+
console.log(JSON.stringify({
|
|
88
|
+
included: report.included.map((s) => ({
|
|
89
|
+
name: s.name,
|
|
90
|
+
class: s.class,
|
|
91
|
+
method: s.method,
|
|
92
|
+
path: s.path,
|
|
93
|
+
readOnly: s.readOnly,
|
|
94
|
+
requiresApproval: s.requiresApproval,
|
|
95
|
+
})),
|
|
96
|
+
denied: report.denied.map((s) => ({
|
|
97
|
+
name: s.name,
|
|
98
|
+
reason: s.denyReason,
|
|
99
|
+
})),
|
|
100
|
+
warnings: report.warnings,
|
|
101
|
+
next: 'gate.register(toolRegistry, "your-agent")',
|
|
102
|
+
}, null, 2));
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
// eslint-disable-next-line no-console
|
|
106
|
+
console.error(e);
|
|
107
|
+
process.exitCode = 1;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
skillgate
|
|
111
|
+
.command('init')
|
|
112
|
+
.description('Write a starter skillgate.config.json in the current directory')
|
|
113
|
+
.option('--force', 'Overwrite existing file')
|
|
114
|
+
.action((opts) => {
|
|
115
|
+
const out = path.resolve(process.cwd(), 'skillgate.config.json');
|
|
116
|
+
if (fs.existsSync(out) && !opts.force) {
|
|
117
|
+
// eslint-disable-next-line no-console
|
|
118
|
+
console.error(`Refusing to overwrite ${out} (pass --force)`);
|
|
119
|
+
process.exitCode = 1;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const starter = {
|
|
123
|
+
$schema: 'https://hazeljs.ai/schemas/skillgate.config.json',
|
|
124
|
+
include: {
|
|
125
|
+
mode: 'opt-in',
|
|
126
|
+
tags: ['agent', 'skillgate'],
|
|
127
|
+
},
|
|
128
|
+
classify: {
|
|
129
|
+
writeRequiresApproval: true,
|
|
130
|
+
allowDestructive: false,
|
|
131
|
+
allowAdmin: false,
|
|
132
|
+
},
|
|
133
|
+
invoke: {
|
|
134
|
+
baseUrl: 'http://127.0.0.1:3000',
|
|
135
|
+
headers: {
|
|
136
|
+
Authorization: 'Bearer ${API_TOKEN}',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
warnAbove: 12,
|
|
140
|
+
maxTools: 24,
|
|
141
|
+
agentName: 'api-concierge',
|
|
142
|
+
};
|
|
143
|
+
fs.writeFileSync(out, JSON.stringify(starter, null, 2) + '\n');
|
|
144
|
+
// eslint-disable-next-line no-console
|
|
145
|
+
console.log(`Wrote ${out}`);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `hazel store publish|install|list|remove|doctor` — local or hosted Agent OS package registry.
|
|
4
|
+
* Hosted (Cloud Team SKU): `--remote <url> --token <token>` or HAZEL_REGISTRY_URL / HAZEL_REGISTRY_TOKEN.
|
|
5
|
+
* `hazel install` aliases `hazel store install`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerStoreCommand(program: Command): void;
|
|
@@ -0,0 +1,203 @@
|
|
|
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.registerStoreCommand = registerStoreCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
async function resolveRegistry(opts) {
|
|
40
|
+
const { createAgentPackageRegistry } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent')));
|
|
41
|
+
return createAgentPackageRegistry({
|
|
42
|
+
remote: opts.remote,
|
|
43
|
+
token: opts.token,
|
|
44
|
+
registryRoot: opts.registry,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function registryOptions(cmd) {
|
|
48
|
+
return cmd
|
|
49
|
+
.option('--registry <dir>', 'Local registry root (default: ~/.hazel/registry)')
|
|
50
|
+
.option('--remote <url>', 'Hosted registry base URL (Cloud Team SKU; env HAZEL_REGISTRY_URL)')
|
|
51
|
+
.option('--token <token>', 'Bearer token for hosted registry (env HAZEL_REGISTRY_TOKEN)');
|
|
52
|
+
}
|
|
53
|
+
async function publishAction(file, opts) {
|
|
54
|
+
const { loadMarketplacePackage } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent')));
|
|
55
|
+
const pkg = loadMarketplacePackage(path.resolve(process.cwd(), file));
|
|
56
|
+
const registry = await resolveRegistry(opts);
|
|
57
|
+
await registry.publish(pkg);
|
|
58
|
+
// eslint-disable-next-line no-console
|
|
59
|
+
console.log(JSON.stringify({
|
|
60
|
+
ok: true,
|
|
61
|
+
action: 'publish',
|
|
62
|
+
package: pkg.name,
|
|
63
|
+
version: pkg.version,
|
|
64
|
+
registry: registry.location,
|
|
65
|
+
kind: registry.kind,
|
|
66
|
+
}, null, 2));
|
|
67
|
+
}
|
|
68
|
+
async function installAction(spec, opts) {
|
|
69
|
+
const { loadMarketplacePackage, materializeAgentPackage, parsePackageSpec } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent')));
|
|
70
|
+
const projectRoot = path.resolve(process.cwd(), opts.cwd);
|
|
71
|
+
const resolvedPath = path.resolve(process.cwd(), spec);
|
|
72
|
+
const looksLikeFile = spec.includes(path.sep) ||
|
|
73
|
+
spec.includes('/') ||
|
|
74
|
+
spec.endsWith('.json') ||
|
|
75
|
+
fs.existsSync(resolvedPath);
|
|
76
|
+
let pkg;
|
|
77
|
+
if (looksLikeFile && fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isFile()) {
|
|
78
|
+
pkg = loadMarketplacePackage(resolvedPath);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const { name, version } = parsePackageSpec(spec);
|
|
82
|
+
const registry = await resolveRegistry(opts);
|
|
83
|
+
pkg = await registry.get(name, version);
|
|
84
|
+
}
|
|
85
|
+
const result = materializeAgentPackage(pkg, projectRoot);
|
|
86
|
+
// eslint-disable-next-line no-console
|
|
87
|
+
console.log(JSON.stringify({
|
|
88
|
+
ok: true,
|
|
89
|
+
action: 'install',
|
|
90
|
+
package: result.packageName,
|
|
91
|
+
version: result.version,
|
|
92
|
+
path: result.packagePath,
|
|
93
|
+
lock: result.lockPath,
|
|
94
|
+
note: 'Use hazel agent run with the materialized package DNA, or runtime.installAgentPackage for hot-reload',
|
|
95
|
+
}, null, 2));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* `hazel store publish|install|list|remove|doctor` — local or hosted Agent OS package registry.
|
|
99
|
+
* Hosted (Cloud Team SKU): `--remote <url> --token <token>` or HAZEL_REGISTRY_URL / HAZEL_REGISTRY_TOKEN.
|
|
100
|
+
* `hazel install` aliases `hazel store install`.
|
|
101
|
+
*/
|
|
102
|
+
function registerStoreCommand(program) {
|
|
103
|
+
const store = program
|
|
104
|
+
.command('store')
|
|
105
|
+
.description('Agent OS package registry — local filesystem or hosted (--remote) Cloud Team registry');
|
|
106
|
+
registryOptions(store
|
|
107
|
+
.command('publish')
|
|
108
|
+
.description('Publish a marketplace / DNA JSON package to the registry')
|
|
109
|
+
.argument('<file>', 'Path to .dna.json or marketplace package JSON')).action(async (file, opts) => {
|
|
110
|
+
try {
|
|
111
|
+
await publishAction(file, opts);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
// eslint-disable-next-line no-console
|
|
115
|
+
console.error(e instanceof Error ? e.message : e);
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
registryOptions(store
|
|
120
|
+
.command('install')
|
|
121
|
+
.description('Install a package into the project (.hazel/agents). Spec: path, name, or name@version')
|
|
122
|
+
.argument('<spec>', 'File path or package name[@version]')
|
|
123
|
+
.option('--cwd <dir>', 'Project root', '.')).action(async (spec, opts) => {
|
|
124
|
+
try {
|
|
125
|
+
await installAction(spec, opts);
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
// eslint-disable-next-line no-console
|
|
129
|
+
console.error(e instanceof Error ? e.message : e);
|
|
130
|
+
process.exitCode = 1;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
registryOptions(store
|
|
134
|
+
.command('list')
|
|
135
|
+
.description('List packages in the registry')
|
|
136
|
+
.argument('[query]', 'Optional name/description filter')).action(async (query, opts) => {
|
|
137
|
+
try {
|
|
138
|
+
const registry = await resolveRegistry(opts);
|
|
139
|
+
const packages = await registry.list(query);
|
|
140
|
+
// eslint-disable-next-line no-console
|
|
141
|
+
console.log(JSON.stringify({ ok: true, kind: registry.kind, registry: registry.location, packages }, null, 2));
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
// eslint-disable-next-line no-console
|
|
145
|
+
console.error(e instanceof Error ? e.message : e);
|
|
146
|
+
process.exitCode = 1;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
registryOptions(store
|
|
150
|
+
.command('remove')
|
|
151
|
+
.description('Remove a package (or one version) from the registry')
|
|
152
|
+
.argument('<spec>', 'name or name@version')).action(async (spec, opts) => {
|
|
153
|
+
try {
|
|
154
|
+
const { parsePackageSpec } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent')));
|
|
155
|
+
const { name, version } = parsePackageSpec(spec);
|
|
156
|
+
const registry = await resolveRegistry(opts);
|
|
157
|
+
await registry.remove(name, version);
|
|
158
|
+
// eslint-disable-next-line no-console
|
|
159
|
+
console.log(JSON.stringify({
|
|
160
|
+
ok: true,
|
|
161
|
+
action: 'remove',
|
|
162
|
+
name,
|
|
163
|
+
version: version ?? '*',
|
|
164
|
+
kind: registry.kind,
|
|
165
|
+
registry: registry.location,
|
|
166
|
+
}, null, 2));
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
// eslint-disable-next-line no-console
|
|
170
|
+
console.error(e instanceof Error ? e.message : e);
|
|
171
|
+
process.exitCode = 1;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
registryOptions(store.command('doctor').description('Check registry health (local or remote)')).action(async (opts) => {
|
|
175
|
+
try {
|
|
176
|
+
const registry = await resolveRegistry(opts);
|
|
177
|
+
const report = await registry.doctor();
|
|
178
|
+
// eslint-disable-next-line no-console
|
|
179
|
+
console.log(JSON.stringify({ ...report, kind: registry.kind, registry: registry.location }, null, 2));
|
|
180
|
+
if (!report.ok)
|
|
181
|
+
process.exitCode = 1;
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
// eslint-disable-next-line no-console
|
|
185
|
+
console.error(e instanceof Error ? e.message : e);
|
|
186
|
+
process.exitCode = 1;
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
registryOptions(program
|
|
190
|
+
.command('install')
|
|
191
|
+
.description('Alias for hazel store install')
|
|
192
|
+
.argument('<spec>', 'File path or package name[@version]')
|
|
193
|
+
.option('--cwd <dir>', 'Project root', '.')).action(async (spec, opts) => {
|
|
194
|
+
try {
|
|
195
|
+
await installAction(spec, opts);
|
|
196
|
+
}
|
|
197
|
+
catch (e) {
|
|
198
|
+
// eslint-disable-next-line no-console
|
|
199
|
+
console.error(e instanceof Error ? e.message : e);
|
|
200
|
+
process.exitCode = 1;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
const commander_1 = require("commander");
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const store_1 = require("./store");
|
|
41
|
+
describe('registerStoreCommand (G2 Package+Store)', () => {
|
|
42
|
+
it('registers store subcommands and install alias', () => {
|
|
43
|
+
const program = new commander_1.Command();
|
|
44
|
+
(0, store_1.registerStoreCommand)(program);
|
|
45
|
+
const store = program.commands.find((c) => c.name() === 'store');
|
|
46
|
+
expect(store).toBeDefined();
|
|
47
|
+
const names = store.commands.map((c) => c.name());
|
|
48
|
+
expect(names).toEqual(expect.arrayContaining(['publish', 'install', 'list', 'remove', 'doctor']));
|
|
49
|
+
expect(program.commands.some((c) => c.name() === 'install')).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
it('publish then install materializes support-desk style package', async () => {
|
|
52
|
+
const { exportAgentDna, toMarketplacePackage, saveMarketplacePackage } = await Promise.resolve().then(() => __importStar(require('@hazeljs/agent')));
|
|
53
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'hazel-store-cli-'));
|
|
54
|
+
const registryDir = path.join(tmp, 'registry');
|
|
55
|
+
const projectDir = path.join(tmp, 'project');
|
|
56
|
+
fs.mkdirSync(projectDir);
|
|
57
|
+
const dna = exportAgentDna({
|
|
58
|
+
name: 'support-desk',
|
|
59
|
+
version: '1.0.0',
|
|
60
|
+
tools: [{ name: 'lookupOrder' }],
|
|
61
|
+
});
|
|
62
|
+
const pkg = toMarketplacePackage(dna);
|
|
63
|
+
pkg.name = '@hazeljs/support-desk-agent';
|
|
64
|
+
const pkgFile = path.join(tmp, 'support-desk.marketplace.json');
|
|
65
|
+
saveMarketplacePackage(pkg, pkgFile);
|
|
66
|
+
const program = new commander_1.Command();
|
|
67
|
+
(0, store_1.registerStoreCommand)(program);
|
|
68
|
+
await program.parseAsync(['store', 'publish', pkgFile, '--registry', registryDir], {
|
|
69
|
+
from: 'user',
|
|
70
|
+
});
|
|
71
|
+
expect(process.exitCode ?? 0).toBe(0);
|
|
72
|
+
await program.parseAsync([
|
|
73
|
+
'store',
|
|
74
|
+
'install',
|
|
75
|
+
'@hazeljs/support-desk-agent@1.0.0',
|
|
76
|
+
'--cwd',
|
|
77
|
+
projectDir,
|
|
78
|
+
'--registry',
|
|
79
|
+
registryDir,
|
|
80
|
+
], { from: 'user' });
|
|
81
|
+
expect(process.exitCode ?? 0).toBe(0);
|
|
82
|
+
const lockPath = path.join(projectDir, '.hazel', 'agents', 'lock.json');
|
|
83
|
+
expect(fs.existsSync(lockPath)).toBe(true);
|
|
84
|
+
const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
|
|
85
|
+
expect(lock['@hazeljs/support-desk-agent']?.version).toBe('1.0.0');
|
|
86
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
87
|
+
});
|
|
88
|
+
it('publishes and installs real starter support-desk.marketplace.json', async () => {
|
|
89
|
+
// Fixture is vendored in-package so CI (hazeljs repo only) does not need sibling starters.
|
|
90
|
+
const pkgFile = path.resolve(__dirname, '../../fixtures/support-desk.marketplace.json');
|
|
91
|
+
expect(fs.existsSync(pkgFile)).toBe(true);
|
|
92
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'hazel-store-starter-'));
|
|
93
|
+
const registryDir = path.join(tmp, 'registry');
|
|
94
|
+
const projectDir = path.join(tmp, 'project');
|
|
95
|
+
fs.mkdirSync(projectDir);
|
|
96
|
+
const program = new commander_1.Command();
|
|
97
|
+
(0, store_1.registerStoreCommand)(program);
|
|
98
|
+
process.exitCode = 0;
|
|
99
|
+
await program.parseAsync(['store', 'publish', pkgFile, '--registry', registryDir], {
|
|
100
|
+
from: 'user',
|
|
101
|
+
});
|
|
102
|
+
expect(process.exitCode ?? 0).toBe(0);
|
|
103
|
+
await program.parseAsync([
|
|
104
|
+
'store',
|
|
105
|
+
'install',
|
|
106
|
+
'@hazeljs/support-desk-agent',
|
|
107
|
+
'--cwd',
|
|
108
|
+
projectDir,
|
|
109
|
+
'--registry',
|
|
110
|
+
registryDir,
|
|
111
|
+
], { from: 'user' });
|
|
112
|
+
expect(process.exitCode ?? 0).toBe(0);
|
|
113
|
+
const packageJson = path.join(projectDir, '.hazel', 'agents', 'hazeljs__support-desk-agent', 'package.json');
|
|
114
|
+
expect(fs.existsSync(packageJson)).toBe(true);
|
|
115
|
+
const loaded = JSON.parse(fs.readFileSync(packageJson, 'utf8'));
|
|
116
|
+
expect(loaded.name).toBe('@hazeljs/support-desk-agent');
|
|
117
|
+
expect(loaded.dna.name).toBe('support-desk');
|
|
118
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
119
|
+
});
|
|
120
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -56,6 +56,8 @@ const add_1 = require("./commands/add");
|
|
|
56
56
|
const eval_1 = require("./commands/eval");
|
|
57
57
|
const benchmark_1 = require("./commands/benchmark");
|
|
58
58
|
const agent_1 = require("./commands/agent");
|
|
59
|
+
const skillgate_1 = require("./commands/skillgate");
|
|
60
|
+
const store_1 = require("./commands/store");
|
|
59
61
|
// Read version from package.json to ensure consistency
|
|
60
62
|
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json'), 'utf8'));
|
|
61
63
|
const program = new commander_1.Command();
|
|
@@ -71,6 +73,8 @@ program
|
|
|
71
73
|
(0, eval_1.registerEvalCommand)(program);
|
|
72
74
|
(0, benchmark_1.registerBenchmarkCommand)(program);
|
|
73
75
|
(0, agent_1.registerAgentCommand)(program);
|
|
76
|
+
(0, skillgate_1.registerSkillgateCommand)(program);
|
|
77
|
+
(0, store_1.registerStoreCommand)(program);
|
|
74
78
|
// Generate command group (unified: hazel g <type> <name> [--path] [--dry-run] [--json], or hazel g --list)
|
|
75
79
|
const generateCommand = program
|
|
76
80
|
.command('generate')
|
|
@@ -234,6 +234,25 @@ export const mlImports = [MLModule.forRoot()];
|
|
|
234
234
|
// Minimal MCP server example:
|
|
235
235
|
const server = createMcpServer({ name: 'hazel-mcp', version: '0.1.0' });
|
|
236
236
|
server.start();
|
|
237
|
+
`,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
shortName: 'skillgate',
|
|
241
|
+
npm: '@hazeljs/skillgate',
|
|
242
|
+
label: 'Skillgate - OpenAPI → governed agent skills (@hazeljs/skillgate)',
|
|
243
|
+
hint: 'import { Skillgate } from "@hazeljs/skillgate";\n // Skillgate.fromOpenApi(spec).register(toolRegistry, "api-concierge");',
|
|
244
|
+
moduleImport: null,
|
|
245
|
+
moduleExpression: null,
|
|
246
|
+
setupTemplate: `import { Skillgate } from '@hazeljs/skillgate';
|
|
247
|
+
import { ToolRegistry } from '@hazeljs/agent';
|
|
248
|
+
|
|
249
|
+
// Opt-in: tags agent|skillgate, x-hazel-skill, or explicit allowlists.
|
|
250
|
+
const gate = Skillgate.fromOpenApi(openApiSpec, {
|
|
251
|
+
include: { tags: ['agent'] },
|
|
252
|
+
invoke: { baseUrl: process.env.API_BASE_URL || 'http://127.0.0.1:3000' },
|
|
253
|
+
});
|
|
254
|
+
const registry = new ToolRegistry();
|
|
255
|
+
gate.register(registry, 'api-concierge');
|
|
237
256
|
`,
|
|
238
257
|
},
|
|
239
258
|
{
|