@hazeljs/cli 0.8.0 → 0.8.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/package.json +1 -1
- package/cli-manifest.json +1 -1
- package/dist/commands/eval.d.ts +6 -0
- package/dist/commands/eval.js +65 -0
- package/dist/commands/generate-auth.js +31 -13
- package/dist/commands/generate-simple.js +12 -0
- package/dist/commands/templates.d.ts +1 -0
- package/dist/commands/templates.js +35 -1
- package/dist/index.js +2 -0
- package/package.json +9 -5
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": "0.8.
|
|
7
|
+
"version": "0.8.1",
|
|
8
8
|
"description": "CLI for generating HazelJS components and applications"
|
|
9
9
|
},
|
|
10
10
|
"commands": [
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `hazel eval <dataset.json>` — load a golden dataset and run a placeholder pass-through runner.
|
|
4
|
+
* Wire your own runner in app code using @hazeljs/eval (see runGoldenDataset).
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerEvalCommand(program: Command): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
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.registerEvalCommand = registerEvalCommand;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
/**
|
|
39
|
+
* `hazel eval <dataset.json>` — load a golden dataset and run a placeholder pass-through runner.
|
|
40
|
+
* Wire your own runner in app code using @hazeljs/eval (see runGoldenDataset).
|
|
41
|
+
*/
|
|
42
|
+
function registerEvalCommand(program) {
|
|
43
|
+
program
|
|
44
|
+
.command('eval')
|
|
45
|
+
.description('Run a golden dataset JSON through @hazeljs/eval (smoke check; supply your runner in code)')
|
|
46
|
+
.argument('<dataset>', 'Path to golden dataset JSON')
|
|
47
|
+
.option('--ci', 'Set exit code 1 when eval fails thresholds')
|
|
48
|
+
.action(async (dataset, opts) => {
|
|
49
|
+
try {
|
|
50
|
+
const { loadGoldenDatasetFromJson, runGoldenDataset, reportEvalForCi } = await Promise.resolve().then(() => __importStar(require('@hazeljs/eval')));
|
|
51
|
+
const ds = loadGoldenDatasetFromJson(path.resolve(process.cwd(), dataset));
|
|
52
|
+
const result = await runGoldenDataset(ds, async ({ input }) => ({
|
|
53
|
+
output: input,
|
|
54
|
+
toolCalls: [],
|
|
55
|
+
retrievedIds: [],
|
|
56
|
+
}), { minAverageScore: 0 });
|
|
57
|
+
reportEvalForCi(result, { exitOnFail: Boolean(opts.ci) });
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
// eslint-disable-next-line no-console
|
|
61
|
+
console.error(e);
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -22,9 +22,13 @@ export class AuthModule {}
|
|
|
22
22
|
`;
|
|
23
23
|
const AUTH_SERVICE_TEMPLATE = `import { Service, BadRequestError, UnauthorizedError } from '@hazeljs/core';
|
|
24
24
|
import { JwtService } from '@hazeljs/auth';
|
|
25
|
+
import * as bcrypt from 'bcryptjs';
|
|
25
26
|
import { RegisterDto } from './dto/register.dto';
|
|
26
27
|
import { LoginDto } from './dto/login.dto';
|
|
27
28
|
|
|
29
|
+
/** Replace with your DB / Prisma / TypeORM repository */
|
|
30
|
+
const users = new Map<string, { id: string; name: string; email: string; passwordHash: string }>();
|
|
31
|
+
|
|
28
32
|
@Service()
|
|
29
33
|
export class AuthService {
|
|
30
34
|
constructor(
|
|
@@ -32,38 +36,52 @@ export class AuthService {
|
|
|
32
36
|
) {}
|
|
33
37
|
|
|
34
38
|
async register(registerDto: RegisterDto) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
const email = registerDto.email.toLowerCase();
|
|
40
|
+
if (users.has(email)) {
|
|
41
|
+
throw new BadRequestError('User already exists');
|
|
42
|
+
}
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
const passwordHash = await bcrypt.hash(registerDto.password, 10);
|
|
41
45
|
const user = {
|
|
42
46
|
id: Date.now().toString(),
|
|
43
47
|
name: registerDto.name,
|
|
44
|
-
email
|
|
48
|
+
email,
|
|
49
|
+
passwordHash,
|
|
45
50
|
};
|
|
51
|
+
users.set(email, user);
|
|
46
52
|
|
|
47
53
|
const accessToken = this.jwtService.sign({
|
|
48
54
|
sub: user.id,
|
|
49
55
|
email: user.email,
|
|
50
56
|
});
|
|
51
57
|
|
|
52
|
-
return {
|
|
58
|
+
return {
|
|
59
|
+
user: { id: user.id, name: user.name, email: user.email },
|
|
60
|
+
accessToken,
|
|
61
|
+
};
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
async login(loginDto: LoginDto) {
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
const email = loginDto.email.toLowerCase();
|
|
66
|
+
const row = users.get(email);
|
|
67
|
+
if (!row) {
|
|
68
|
+
throw new UnauthorizedError('Invalid credentials');
|
|
69
|
+
}
|
|
58
70
|
|
|
59
|
-
const
|
|
71
|
+
const ok = await bcrypt.compare(loginDto.password, row.passwordHash);
|
|
72
|
+
if (!ok) {
|
|
73
|
+
throw new UnauthorizedError('Invalid credentials');
|
|
74
|
+
}
|
|
60
75
|
|
|
61
76
|
const accessToken = this.jwtService.sign({
|
|
62
|
-
sub:
|
|
63
|
-
email:
|
|
77
|
+
sub: row.id,
|
|
78
|
+
email: row.email,
|
|
64
79
|
});
|
|
65
80
|
|
|
66
|
-
return {
|
|
81
|
+
return {
|
|
82
|
+
user: { id: row.id, name: row.name, email: row.email },
|
|
83
|
+
accessToken,
|
|
84
|
+
};
|
|
67
85
|
}
|
|
68
86
|
}
|
|
69
87
|
`;
|
|
@@ -133,6 +133,18 @@ exports.SIMPLE_GENERATORS = [
|
|
|
133
133
|
'Configure your embedding provider and vector store',
|
|
134
134
|
],
|
|
135
135
|
},
|
|
136
|
+
{
|
|
137
|
+
type: 'rag-pipeline',
|
|
138
|
+
description: 'RAG pipeline service (RAGPipeline.from + memory store)',
|
|
139
|
+
suffix: 'rag-pipeline',
|
|
140
|
+
template: templates_1.RAG_PIPELINE_TEMPLATE,
|
|
141
|
+
nameRequired: true,
|
|
142
|
+
nextSteps: [
|
|
143
|
+
'npm install @hazeljs/rag',
|
|
144
|
+
'Wire llm() to HazelAI or AIService',
|
|
145
|
+
'For production vectors, use HazelAI persistence.rag or construct RAGPipeline with your VectorStore',
|
|
146
|
+
],
|
|
147
|
+
},
|
|
136
148
|
{
|
|
137
149
|
type: 'discovery',
|
|
138
150
|
description: 'Service discovery setup',
|
|
@@ -28,6 +28,7 @@ export declare const AGENT_TEMPLATE = "import { Agent, Tool } from '@hazeljs/age
|
|
|
28
28
|
export declare const CACHE_SERVICE_TEMPLATE = "import { Service } from '@hazeljs/core';\nimport { CacheService, Cacheable, CacheEvict } from '@hazeljs/cache';\n\n@Service()\nexport class {{className}}CacheService {\n constructor(private readonly cacheService: CacheService) {}\n\n @Cacheable({ key: '{{fileName}}:all', ttl: 60 })\n async findAll() {\n // This result will be cached for 60 seconds\n return [];\n }\n\n @Cacheable({ key: '{{fileName}}:{{=<% %>=}}#{id}<%={{ }}=%>', ttl: 300 })\n async findOne(id: string) {\n // This result will be cached for 5 minutes\n return { id };\n }\n\n @CacheEvict({ key: '{{fileName}}:all' })\n async create(data: any) {\n // Creating a new item evicts the list cache\n return data;\n }\n\n async clearAll() {\n await this.cacheService.clear();\n }\n}\n";
|
|
29
29
|
export declare const CRON_SERVICE_TEMPLATE = "import { Service } from '@hazeljs/core';\nimport { Cron, CronExpression } from '@hazeljs/cron';\n\n@Service()\nexport class {{className}}CronService {\n @Cron(CronExpression.EVERY_MINUTE)\n handleEveryMinute() {\n console.log('[{{className}}Cron] Running every minute...');\n // Add your cron job logic here\n }\n\n @Cron('0 0 * * *') // Every day at midnight\n handleDaily() {\n console.log('[{{className}}Cron] Running daily task...');\n // Add your daily task logic here\n }\n\n @Cron(CronExpression.EVERY_HOUR)\n handleHourly() {\n console.log('[{{className}}Cron] Running hourly cleanup...');\n // Add your hourly task logic here\n }\n}\n";
|
|
30
30
|
export declare const RAG_SERVICE_TEMPLATE = "import { Service } from '@hazeljs/core';\nimport { RAGPipeline, MemoryVectorStore } from '@hazeljs/rag';\n\n@Service()\nexport class {{className}}RagService {\n private pipeline: RAGPipeline;\n\n constructor() {\n // Initialize with a memory vector store (swap for Pinecone, Qdrant, etc. in production)\n const vectorStore = new MemoryVectorStore();\n\n this.pipeline = new RAGPipeline({\n vectorStore,\n topK: 5,\n });\n }\n\n async addDocument(content: string, metadata?: Record<string, unknown>) {\n // Add a document to the vector store for retrieval\n await this.pipeline.addDocument({\n content,\n metadata: metadata || {},\n });\n }\n\n async query(question: string) {\n // Retrieve relevant documents and generate a response\n const results = await this.pipeline.query(question);\n return results;\n }\n}\n";
|
|
31
|
+
export declare const RAG_PIPELINE_TEMPLATE = "import { Service } from '@hazeljs/core';\nimport { RAGPipeline } from '@hazeljs/rag';\n\n/**\n * RAG pipeline scaffold \u2014 uses {@link RAGPipeline.from} with in-memory vectors.\n * Swap persistence via HazelAI `persistence.rag` or construct {@link RAGPipeline} with Pinecone/Qdrant/Weaviate/Chroma.\n */\n@Service()\nexport class {{className}}RagPipelineService {\n private pipeline: RAGPipeline | null = null;\n\n async ensurePipeline(): Promise<RAGPipeline> {\n if (this.pipeline) return this.pipeline;\n this.pipeline = RAGPipeline.from({\n provider: 'openai',\n vectorStore: 'memory',\n topK: 5,\n chunkSize: 1000,\n chunkOverlap: 200,\n llm: async (prompt: string) => {\n // Wire to your LLM (HazelAI, AIService, or HTTP)\n return prompt;\n },\n });\n await this.pipeline.initialize();\n return this.pipeline;\n }\n\n async query(question: string) {\n const p = await this.ensurePipeline();\n return p.query(question);\n }\n}\n";
|
|
31
32
|
export declare const DISCOVERY_TEMPLATE = "import { Service } from '@hazeljs/core';\nimport { ServiceRegistry, DiscoveryClient } from '@hazeljs/discovery';\n\n@Service()\nexport class {{className}}DiscoveryService {\n constructor(\n private readonly registry: ServiceRegistry,\n private readonly client: DiscoveryClient,\n ) {}\n\n async registerService() {\n await this.registry.register({\n name: '{{fileName}}-service',\n host: 'localhost',\n port: 3000,\n metadata: {\n version: '1.0.0',\n },\n });\n }\n\n async discoverService(serviceName: string) {\n const instances = await this.client.getInstances(serviceName);\n return instances;\n }\n}\n";
|
|
32
33
|
export declare const CONFIG_TEMPLATE = "import { HazelModule } from '@hazeljs/core';\nimport { ConfigModule, ConfigService } from '@hazeljs/config';\n\n// Import ConfigModule.forRoot() in your app module:\n//\n// @HazelModule({\n// imports: [\n// ConfigModule.forRoot({\n// envFilePath: '.env',\n// }),\n// ],\n// })\n//\n// Then inject ConfigService wherever you need it:\n//\n// constructor(private readonly config: ConfigService) {}\n//\n// Usage:\n// this.config.get('DATABASE_URL');\n// this.config.get('PORT', '3000'); // with default value\n\nexport { ConfigModule, ConfigService };\n";
|
|
33
34
|
export declare const SERVERLESS_LAMBDA_TEMPLATE = "import { createLambdaHandler } from '@hazeljs/serverless';\nimport { AppModule } from './app.module';\n\nexport const handler = createLambdaHandler(AppModule);\n";
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* here and add a config entry in generate-simple.ts.
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.SERVERLESS_CLOUD_FUNCTION_TEMPLATE = exports.SERVERLESS_LAMBDA_TEMPLATE = exports.CONFIG_TEMPLATE = exports.DISCOVERY_TEMPLATE = exports.RAG_SERVICE_TEMPLATE = exports.CRON_SERVICE_TEMPLATE = exports.CACHE_SERVICE_TEMPLATE = exports.AGENT_TEMPLATE = exports.AI_SERVICE_TEMPLATE = exports.WEBSOCKET_GATEWAY_TEMPLATE = exports.REPOSITORY_TEMPLATE = exports.EXCEPTION_FILTER_TEMPLATE = exports.PIPE_TEMPLATE = exports.MIDDLEWARE_TEMPLATE = exports.INTERCEPTOR_TEMPLATE = exports.GUARD_TEMPLATE = exports.SERVICE_TEMPLATE = exports.CONTROLLER_TEMPLATE = void 0;
|
|
19
|
+
exports.SERVERLESS_CLOUD_FUNCTION_TEMPLATE = exports.SERVERLESS_LAMBDA_TEMPLATE = exports.CONFIG_TEMPLATE = exports.DISCOVERY_TEMPLATE = exports.RAG_PIPELINE_TEMPLATE = exports.RAG_SERVICE_TEMPLATE = exports.CRON_SERVICE_TEMPLATE = exports.CACHE_SERVICE_TEMPLATE = exports.AGENT_TEMPLATE = exports.AI_SERVICE_TEMPLATE = exports.WEBSOCKET_GATEWAY_TEMPLATE = exports.REPOSITORY_TEMPLATE = exports.EXCEPTION_FILTER_TEMPLATE = exports.PIPE_TEMPLATE = exports.MIDDLEWARE_TEMPLATE = exports.INTERCEPTOR_TEMPLATE = exports.GUARD_TEMPLATE = exports.SERVICE_TEMPLATE = exports.CONTROLLER_TEMPLATE = void 0;
|
|
20
20
|
// ── Core framework generators ────────────────────────────────────────────────
|
|
21
21
|
exports.CONTROLLER_TEMPLATE = `import { Controller, Get, Post, Body, Param, Delete, Put } from '@hazeljs/core';
|
|
22
22
|
import { {{className}}Service } from './{{fileName}}.service';
|
|
@@ -324,6 +324,40 @@ export class {{className}}RagService {
|
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
`;
|
|
327
|
+
exports.RAG_PIPELINE_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
328
|
+
import { RAGPipeline } from '@hazeljs/rag';
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* RAG pipeline scaffold — uses {@link RAGPipeline.from} with in-memory vectors.
|
|
332
|
+
* Swap persistence via HazelAI \`persistence.rag\` or construct {@link RAGPipeline} with Pinecone/Qdrant/Weaviate/Chroma.
|
|
333
|
+
*/
|
|
334
|
+
@Service()
|
|
335
|
+
export class {{className}}RagPipelineService {
|
|
336
|
+
private pipeline: RAGPipeline | null = null;
|
|
337
|
+
|
|
338
|
+
async ensurePipeline(): Promise<RAGPipeline> {
|
|
339
|
+
if (this.pipeline) return this.pipeline;
|
|
340
|
+
this.pipeline = RAGPipeline.from({
|
|
341
|
+
provider: 'openai',
|
|
342
|
+
vectorStore: 'memory',
|
|
343
|
+
topK: 5,
|
|
344
|
+
chunkSize: 1000,
|
|
345
|
+
chunkOverlap: 200,
|
|
346
|
+
llm: async (prompt: string) => {
|
|
347
|
+
// Wire to your LLM (HazelAI, AIService, or HTTP)
|
|
348
|
+
return prompt;
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
await this.pipeline.initialize();
|
|
352
|
+
return this.pipeline;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
async query(question: string) {
|
|
356
|
+
const p = await this.ensurePipeline();
|
|
357
|
+
return p.query(question);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
`;
|
|
327
361
|
exports.DISCOVERY_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
328
362
|
import { ServiceRegistry, DiscoveryClient } from '@hazeljs/discovery';
|
|
329
363
|
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,7 @@ const generate_simple_1 = require("./commands/generate-simple");
|
|
|
53
53
|
const generator_registry_1 = require("./utils/generator-registry");
|
|
54
54
|
const info_1 = require("./commands/info");
|
|
55
55
|
const add_1 = require("./commands/add");
|
|
56
|
+
const eval_1 = require("./commands/eval");
|
|
56
57
|
// Read version from package.json to ensure consistency
|
|
57
58
|
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json'), 'utf8'));
|
|
58
59
|
const program = new commander_1.Command();
|
|
@@ -65,6 +66,7 @@ program
|
|
|
65
66
|
// Utility commands
|
|
66
67
|
(0, info_1.infoCommand)(program);
|
|
67
68
|
(0, add_1.addCommand)(program);
|
|
69
|
+
(0, eval_1.registerEvalCommand)(program);
|
|
68
70
|
// Generate command group (unified: hazel g <type> <name> [--path] [--dry-run] [--json], or hazel g --list)
|
|
69
71
|
const generateCommand = program
|
|
70
72
|
.command('generate')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hazeljs/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
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",
|
|
@@ -14,14 +14,18 @@
|
|
|
14
14
|
"hazel": "./dist/index.js"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "tsc && node scripts/generate-manifest.js",
|
|
18
|
-
"build:types": "tsc",
|
|
17
|
+
"build": "tsc -b && node scripts/generate-manifest.js",
|
|
18
|
+
"build:types": "tsc -b",
|
|
19
|
+
"typecheck": "tsc -b --noEmit",
|
|
19
20
|
"test": "jest",
|
|
20
21
|
"lint": "eslint src --ext .ts",
|
|
22
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
21
23
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
22
|
-
"
|
|
24
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
23
26
|
},
|
|
24
27
|
"dependencies": {
|
|
28
|
+
"@hazeljs/eval": "^0.8.1",
|
|
25
29
|
"chalk": "^4.1.2",
|
|
26
30
|
"commander": "^11.1.0",
|
|
27
31
|
"inquirer": "^8.2.7",
|
|
@@ -70,5 +74,5 @@
|
|
|
70
74
|
"type": "opencollective",
|
|
71
75
|
"url": "https://opencollective.com/hazeljs"
|
|
72
76
|
},
|
|
73
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "8b7685d1250c4622f25d83992f58e13a59bb3dba"
|
|
74
78
|
}
|