@hazeljs/cli 0.7.9 → 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.
Files changed (36) hide show
  1. package/@template/.eslintrc.js +4 -18
  2. package/@template/README.md +4 -1
  3. package/@template-ai-native/HazelJS-AI-Native.postman_collection.json +503 -479
  4. package/@template-ai-native/README.md +19 -5
  5. package/@template-ai-native/package.json +1 -1
  6. package/@template-ai-native/prisma/seed.ts +16 -9
  7. package/@template-ai-native/src/agent/agent.controller.ts +20 -8
  8. package/@template-ai-native/src/agent/travel.controller.ts +29 -9
  9. package/@template-ai-native/src/rag/rag.controller.ts +34 -30
  10. package/README.md +35 -27
  11. package/cli-manifest.json +1 -1
  12. package/dist/commands/add.test.js +16 -3
  13. package/dist/commands/eval.d.ts +6 -0
  14. package/dist/commands/eval.js +65 -0
  15. package/dist/commands/generate-app.interactive-packages.test.js +2 -1
  16. package/dist/commands/generate-app.js +5 -4
  17. package/dist/commands/generate-app.new-command.test.js +3 -1
  18. package/dist/commands/generate-app.skeleton.test.js +2 -1
  19. package/dist/commands/generate-auth.js +31 -13
  20. package/dist/commands/generate-auth.test.js +8 -9
  21. package/dist/commands/generate-crud.test.js +7 -9
  22. package/dist/commands/generate-dto.test.js +4 -4
  23. package/dist/commands/generate-module.test.js +10 -10
  24. package/dist/commands/generate-simple.js +173 -19
  25. package/dist/commands/generate-simple.test.js +8 -2
  26. package/dist/commands/info.test.js +1 -3
  27. package/dist/commands/templates.d.ts +1 -0
  28. package/dist/commands/templates.js +35 -1
  29. package/dist/index.js +2 -0
  30. package/dist/index.list.test.js +7 -1
  31. package/dist/index.test.js +7 -1
  32. package/dist/utils/generator-registry.js +17 -3
  33. package/dist/utils/generator.js +3 -1
  34. package/dist/utils/generator.test.js +3 -1
  35. package/dist/utils/packages-registry.js +3 -3
  36. package/package.json +9 -5
@@ -3,7 +3,7 @@
3
3
  A complete AI-native backend application with HazelJS, featuring:
4
4
 
5
5
  - 🤖 **AI Chat Service** - OpenAI-powered chat endpoints
6
- - 🧠 **AI Agents** - Agents with tools and capabilities
6
+ - 🧠 **AI Agents** - Agents with tools and capabilities
7
7
  - 📚 **RAG System** - Document ingestion and semantic search
8
8
  - 🏥 **Health Checks** - Application monitoring
9
9
  - 📊 **Inspector** - Development tools and debugging
@@ -13,29 +13,33 @@ A complete AI-native backend application with HazelJS, featuring:
13
13
  ## Quick Start
14
14
 
15
15
  1. **Install dependencies**
16
+
16
17
  ```bash
17
18
  npm install
18
19
  ```
19
20
 
20
21
  2. **Configure environment**
22
+
21
23
  ```bash
22
24
  cp .env.example .env
23
25
  # Add your OpenAI API key to .env
24
26
  ```
25
27
 
26
28
  3. **Start development server**
29
+
27
30
  ```bash
28
31
  npm run dev
29
32
  ```
30
33
 
31
34
  4. **Visit the application**
32
35
  - App: http://localhost:3000
33
- - Inspector: http://localhost:3000/__hazel
36
+ - Inspector: http://localhost:3000/\_\_hazel
34
37
  - Health: http://localhost:3000/health
35
38
 
36
39
  ## Available Endpoints
37
40
 
38
41
  ### AI Chat
42
+
39
43
  ```bash
40
44
  curl -X POST http://localhost:3000/chat \
41
45
  -H "Content-Type: application/json" \
@@ -43,6 +47,7 @@ curl -X POST http://localhost:3000/chat \
43
47
  ```
44
48
 
45
49
  ### AI Agent (with tools)
50
+
46
51
  ```bash
47
52
  curl -X POST http://localhost:3000/agent \
48
53
  -H "Content-Type: application/json" \
@@ -50,6 +55,7 @@ curl -X POST http://localhost:3000/agent \
50
55
  ```
51
56
 
52
57
  ### RAG Document Ingestion
58
+
53
59
  ```bash
54
60
  curl -X POST http://localhost:3000/rag/ingest \
55
61
  -H "Content-Type: application/json" \
@@ -57,6 +63,7 @@ curl -X POST http://localhost:3000/rag/ingest \
57
63
  ```
58
64
 
59
65
  ### RAG Search
66
+
60
67
  ```bash
61
68
  curl -X POST http://localhost:3000/rag/search \
62
69
  -H "Content-Type: application/json" \
@@ -68,17 +75,20 @@ curl -X POST http://localhost:3000/rag/search \
68
75
  ### Using Docker Compose (Recommended)
69
76
 
70
77
  1. **Configure environment**
78
+
71
79
  ```bash
72
80
  cp .env.example .env
73
81
  # Add your OpenAI API key
74
82
  ```
75
83
 
76
84
  2. **Start all services**
85
+
77
86
  ```bash
78
87
  docker-compose up -d
79
88
  ```
80
89
 
81
90
  3. **View logs**
91
+
82
92
  ```bash
83
93
  docker-compose logs -f hazeljs-ai-app
84
94
  ```
@@ -91,6 +101,7 @@ curl -X POST http://localhost:3000/rag/search \
91
101
  ### Using Docker (Standalone)
92
102
 
93
103
  1. **Build the image**
104
+
94
105
  ```bash
95
106
  docker build -t hazeljs-ai-app .
96
107
  ```
@@ -105,12 +116,13 @@ curl -X POST http://localhost:3000/rag/search \
105
116
  The `docker-compose.yml` includes:
106
117
 
107
118
  - **hazeljs-ai-app** - Main application (port 3000)
108
- - **redis** - Caching and queues (port 6379)
119
+ - **redis** - Caching and queues (port 6379)
109
120
  - **postgres** - Database with pgvector extension (port 5432)
110
121
 
111
122
  ## API Testing with Postman
112
123
 
113
124
  1. **Import the collection**
125
+
114
126
  ```bash
115
127
  # Import HazelJS-AI-Native.postman_collection.json into Postman
116
128
  ```
@@ -178,7 +190,7 @@ npm run db:seed
178
190
  The template uses the `pgvector/pgvector` Docker image which includes the vector extension. Prisma automatically handles the vector indexes when you run `db:push`. The schema includes:
179
191
 
180
192
  - **Vector embeddings** stored as `Float[]` for RAG search
181
- - **Full-text search index** on the `content` field
193
+ - **Full-text search index** on the `content` field
182
194
  - **JSONB index** on the `metadata` field
183
195
 
184
196
  No manual SQL required - Prisma handles everything!
@@ -201,7 +213,7 @@ npm run db:generate
201
213
  The template includes:
202
214
 
203
215
  - **Documents** - RAG document storage with vector embeddings
204
- - **AgentConversations** - AI agent interaction history
216
+ - **AgentConversations** - AI agent interaction history
205
217
  - **ChatHistory** - AI chat session logs
206
218
 
207
219
  ### Using Docker with Database
@@ -254,6 +266,7 @@ npm run format
254
266
  ### Environment Setup
255
267
 
256
268
  1. **Set production variables**
269
+
257
270
  ```bash
258
271
  export NODE_ENV=production
259
272
  export OPENAI_API_KEY=your_production_key
@@ -261,6 +274,7 @@ npm run format
261
274
  ```
262
275
 
263
276
  2. **Deploy with Docker**
277
+
264
278
  ```bash
265
279
  docker-compose -f docker-compose.yml up -d
266
280
  ```
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazeljs-ai-native-app",
3
- "version": "0.7.9",
3
+ "version": "0.8.1",
4
4
  "description": "A HazelJS AI-native application with agents, RAG, and chat",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -15,7 +15,8 @@ async function main() {
15
15
  // Sample documents for RAG demonstration
16
16
  const sampleDocuments = [
17
17
  {
18
- content: 'HazelJS is a TypeScript framework for building AI-native backend applications. It provides built-in support for AI agents, RAG (Retrieval-Augmented Generation), and seamless integration with LLM providers like OpenAI, Anthropic, and Ollama.',
18
+ content:
19
+ 'HazelJS is a TypeScript framework for building AI-native backend applications. It provides built-in support for AI agents, RAG (Retrieval-Augmented Generation), and seamless integration with LLM providers like OpenAI, Anthropic, and Ollama.',
19
20
  metadata: {
20
21
  source: 'documentation',
21
22
  type: 'introduction',
@@ -24,7 +25,8 @@ async function main() {
24
25
  },
25
26
  },
26
27
  {
27
- content: 'TypeScript decorators provide a way to add metadata and modify the behavior of classes, methods, and properties. In HazelJS, decorators like @Controller, @Get, @Post, @Service, and @Agent are used to define the application structure and routing.',
28
+ content:
29
+ 'TypeScript decorators provide a way to add metadata and modify the behavior of classes, methods, and properties. In HazelJS, decorators like @Controller, @Get, @Post, @Service, and @Agent are used to define the application structure and routing.',
28
30
  metadata: {
29
31
  source: 'typescript-guide',
30
32
  type: 'tutorial',
@@ -33,7 +35,8 @@ async function main() {
33
35
  },
34
36
  },
35
37
  {
36
- content: 'AI agents in HazelJS can use tools to perform actions like API calls, database queries, or external service integrations. The @Agent decorator defines an agent, and @Tool decorator defines its capabilities.',
38
+ content:
39
+ 'AI agents in HazelJS can use tools to perform actions like API calls, database queries, or external service integrations. The @Agent decorator defines an agent, and @Tool decorator defines its capabilities.',
37
40
  metadata: {
38
41
  source: 'agent-guide',
39
42
  type: 'tutorial',
@@ -42,7 +45,8 @@ async function main() {
42
45
  },
43
46
  },
44
47
  {
45
- content: 'RAG (Retrieval-Augmented Generation) combines document retrieval with LLM generation to provide more accurate and context-aware responses. HazelJS provides built-in RAG services with vector similarity search.',
48
+ content:
49
+ 'RAG (Retrieval-Augmented Generation) combines document retrieval with LLM generation to provide more accurate and context-aware responses. HazelJS provides built-in RAG services with vector similarity search.',
46
50
  metadata: {
47
51
  source: 'rag-guide',
48
52
  type: 'tutorial',
@@ -51,7 +55,8 @@ async function main() {
51
55
  },
52
56
  },
53
57
  {
54
- content: 'The HazelJS Inspector is a development dashboard available at /__hazel that provides real-time insights into your application, including module dependencies, request metrics, and AI agent performance.',
58
+ content:
59
+ 'The HazelJS Inspector is a development dashboard available at /__hazel that provides real-time insights into your application, including module dependencies, request metrics, and AI agent performance.',
55
60
  metadata: {
56
61
  source: 'development-guide',
57
62
  type: 'tutorial',
@@ -66,7 +71,7 @@ async function main() {
66
71
  try {
67
72
  // Generate embedding for the document
68
73
  const embedding = await embeddings.embed(doc.content);
69
-
74
+
70
75
  // Use raw SQL to insert document with vector embedding
71
76
  await prisma.$executeRaw`
72
77
  INSERT INTO documents (id, content, metadata, embedding, "createdAt", "updatedAt")
@@ -79,7 +84,7 @@ async function main() {
79
84
  NOW()
80
85
  )
81
86
  `;
82
-
87
+
83
88
  console.log(`✅ Created document: ${doc.metadata.source}`);
84
89
  } catch (error) {
85
90
  console.error(`❌ Failed to create document: ${doc.metadata.source}`, error);
@@ -128,14 +133,16 @@ async function main() {
128
133
  {
129
134
  sessionId: 'chat-session-1',
130
135
  userMessage: 'What is HazelJS?',
131
- aiResponse: 'HazelJS is a TypeScript framework for building AI-native backend applications with built-in support for AI agents, RAG, and LLM integration.',
136
+ aiResponse:
137
+ 'HazelJS is a TypeScript framework for building AI-native backend applications with built-in support for AI agents, RAG, and LLM integration.',
132
138
  model: 'gpt-4',
133
139
  tokensUsed: 156,
134
140
  },
135
141
  {
136
142
  sessionId: 'chat-session-1',
137
143
  userMessage: 'How do I create an AI agent?',
138
- aiResponse: 'You can create an AI agent in HazelJS using the @Agent decorator and defining tools with @Tool decorator. Here\'s an example: @Agent({name: "MyAgent"}) class MyAgent { @Tool({description: "My tool"}) async myTool() { return "result"; } }',
144
+ aiResponse:
145
+ 'You can create an AI agent in HazelJS using the @Agent decorator and defining tools with @Tool decorator. Here\'s an example: @Agent({name: "MyAgent"}) class MyAgent { @Tool({description: "My tool"}) async myTool() { return "result"; } }',
139
146
  model: 'gpt-4',
140
147
  tokensUsed: 234,
141
148
  },
@@ -91,16 +91,26 @@ export class WeatherAgent {
91
91
  let celsius: number;
92
92
 
93
93
  switch (fromUnit.toLowerCase()) {
94
- case 'fahrenheit': celsius = (value - 32) * (5 / 9); break;
95
- case 'kelvin': celsius = value - 273.15; break;
96
- default: celsius = value;
94
+ case 'fahrenheit':
95
+ celsius = (value - 32) * (5 / 9);
96
+ break;
97
+ case 'kelvin':
98
+ celsius = value - 273.15;
99
+ break;
100
+ default:
101
+ celsius = value;
97
102
  }
98
103
 
99
104
  let result: number;
100
105
  switch (toUnit.toLowerCase()) {
101
- case 'fahrenheit': result = celsius * (9 / 5) + 32; break;
102
- case 'kelvin': result = celsius + 273.15; break;
103
- default: result = celsius;
106
+ case 'fahrenheit':
107
+ result = celsius * (9 / 5) + 32;
108
+ break;
109
+ case 'kelvin':
110
+ result = celsius + 273.15;
111
+ break;
112
+ default:
113
+ result = celsius;
104
114
  }
105
115
 
106
116
  return {
@@ -134,7 +144,7 @@ export class WeatherAgent {
134
144
  export class AgentController {
135
145
  constructor(
136
146
  private readonly agent: WeatherAgent,
137
- private readonly agentService: AgentService,
147
+ private readonly agentService: AgentService
138
148
  ) {}
139
149
 
140
150
  @Post()
@@ -160,7 +170,9 @@ export class AgentController {
160
170
  if (chunk.type === 'token') {
161
171
  res.write(`data: ${JSON.stringify({ type: 'token', content: chunk.content })}\n\n`);
162
172
  } else if (chunk.type === 'step') {
163
- res.write(`data: ${JSON.stringify({ type: 'step', state: chunk.step.state, tool: chunk.step.action?.toolName ?? null })}\n\n`);
173
+ res.write(
174
+ `data: ${JSON.stringify({ type: 'step', state: chunk.step.state, tool: chunk.step.action?.toolName ?? null })}\n\n`
175
+ );
164
176
  } else if (chunk.type === 'done') {
165
177
  res.write(`data: ${JSON.stringify({ type: 'done', response: chunk.result.response })}\n\n`);
166
178
  }
@@ -7,7 +7,8 @@ import { Agent, Tool, Delegate, AgentService } from '@hazeljs/agent';
7
7
  @Agent({
8
8
  name: 'FactsAgent',
9
9
  description: 'Provides fun facts, cultural highlights, and travel tips about cities',
10
- systemPrompt: 'You are a knowledgeable travel guide. Use your tools to provide interesting facts and tips about cities.',
10
+ systemPrompt:
11
+ 'You are a knowledgeable travel guide. Use your tools to provide interesting facts and tips about cities.',
11
12
  })
12
13
  @Service()
13
14
  export class FactsAgent {
@@ -25,10 +26,26 @@ export class FactsAgent {
25
26
  async getCityFacts(input: { city: string }) {
26
27
  // In real app, call a travel/facts API or use a knowledge base
27
28
  const facts: Record<string, { fact: string; tip: string; bestTime: string }> = {
28
- paris: { fact: 'Paris has more than 470 parks and gardens.', tip: 'Buy a Paris Museum Pass to skip long queues.', bestTime: 'April–June or September–November' },
29
- tokyo: { fact: 'Tokyo has the world\'s busiest pedestrian crossing at Shibuya.', tip: 'Get a Suica card for seamless transit across the city.', bestTime: 'March–May (cherry blossom) or October–November' },
30
- london: { fact: 'London has over 170 museums, most of which are free.', tip: 'The Oyster card gives the cheapest fares on public transport.', bestTime: 'May–September for mild weather' },
31
- newyork: { fact: 'New York City has 468 subway stations — the most in the world.', tip: 'Walk the High Line for great views and free art installations.', bestTime: 'April–June or September–November' },
29
+ paris: {
30
+ fact: 'Paris has more than 470 parks and gardens.',
31
+ tip: 'Buy a Paris Museum Pass to skip long queues.',
32
+ bestTime: 'April–June or September–November',
33
+ },
34
+ tokyo: {
35
+ fact: "Tokyo has the world's busiest pedestrian crossing at Shibuya.",
36
+ tip: 'Get a Suica card for seamless transit across the city.',
37
+ bestTime: 'March–May (cherry blossom) or October–November',
38
+ },
39
+ london: {
40
+ fact: 'London has over 170 museums, most of which are free.',
41
+ tip: 'The Oyster card gives the cheapest fares on public transport.',
42
+ bestTime: 'May–September for mild weather',
43
+ },
44
+ newyork: {
45
+ fact: 'New York City has 468 subway stations — the most in the world.',
46
+ tip: 'Walk the High Line for great views and free art installations.',
47
+ bestTime: 'April–June or September–November',
48
+ },
32
49
  };
33
50
 
34
51
  const key = input.city.toLowerCase().replace(/\s+/g, '');
@@ -49,7 +66,8 @@ export class FactsAgent {
49
66
  @Agent({
50
67
  name: 'TravelAgent',
51
68
  description: 'Travel planning assistant that checks weather and provides itinerary advice',
52
- systemPrompt: 'You are a travel planner. Use your tools to check weather and forecasts for cities, then provide helpful travel advice based on the conditions.',
69
+ systemPrompt:
70
+ 'You are a travel planner. Use your tools to check weather and forecasts for cities, then provide helpful travel advice based on the conditions.',
53
71
  })
54
72
  @Service()
55
73
  export class TravelAgent {
@@ -59,7 +77,8 @@ export class TravelAgent {
59
77
  // The LLM sees it as a regular tool — agent-to-agent is completely transparent.
60
78
  @Delegate({
61
79
  agent: 'WeatherAgent',
62
- description: 'Check weather conditions and forecasts for a city to inform travel recommendations',
80
+ description:
81
+ 'Check weather conditions and forecasts for a city to inform travel recommendations',
63
82
  inputField: 'input',
64
83
  })
65
84
  async checkWeather(input: string): Promise<string> {
@@ -87,7 +106,7 @@ export class TravelAgent {
87
106
  export class TravelController {
88
107
  constructor(
89
108
  private readonly travelAgent: TravelAgent,
90
- private readonly agentService: AgentService,
109
+ private readonly agentService: AgentService
91
110
  ) {}
92
111
 
93
112
  // Feature: Agent Delegation — TravelAgent delegates to WeatherAgent via @Delegate
@@ -107,7 +126,8 @@ export class TravelController {
107
126
  const supervisor = runtime.createSupervisor({
108
127
  name: 'travel-supervisor',
109
128
  workers: ['WeatherAgent', 'FactsAgent'],
110
- systemPrompt: 'You are a travel planning supervisor. Route requests to WeatherAgent for weather/forecast questions and to FactsAgent for city facts, tips, and general travel advice. Combine results when both are relevant.',
129
+ systemPrompt:
130
+ 'You are a travel planning supervisor. Route requests to WeatherAgent for weather/forecast questions and to FactsAgent for city facts, tips, and general travel advice. Combine results when both are relevant.',
111
131
  maxRounds: 6,
112
132
  });
113
133
 
@@ -13,7 +13,7 @@ export class RAGService {
13
13
  apiKey: process.env.OPENAI_API_KEY!,
14
14
  model: 'text-embedding-3-small',
15
15
  });
16
-
16
+
17
17
  // Initialize Prisma for PostgreSQL storage
18
18
  this.prisma = new PrismaClient();
19
19
  }
@@ -23,17 +23,17 @@ export class RAGService {
23
23
  const count = await this.prisma.document.count();
24
24
  console.log(`RAG Service initialized - PostgreSQL vector store ready with ${count} documents`);
25
25
  }
26
-
26
+
27
27
  async onModuleDestroy() {
28
28
  await this.prisma.$disconnect();
29
29
  }
30
30
 
31
31
  async ingestDocument(content: string, metadata?: any) {
32
32
  console.log(`Ingesting document, content length: ${content.length}`);
33
-
33
+
34
34
  // Generate embedding for the document
35
35
  const embedding = await this.embeddings.embed(content);
36
-
36
+
37
37
  // Store in PostgreSQL
38
38
  const document = await this.prisma.document.create({
39
39
  data: {
@@ -46,32 +46,36 @@ export class RAGService {
46
46
  },
47
47
  },
48
48
  });
49
-
49
+
50
50
  const totalDocuments = await this.prisma.document.count();
51
- console.log(`Document ingested successfully. ID: ${document.id}, Total documents: ${totalDocuments}`);
52
-
53
- return {
54
- id: document.id,
51
+ console.log(
52
+ `Document ingested successfully. ID: ${document.id}, Total documents: ${totalDocuments}`
53
+ );
54
+
55
+ return {
56
+ id: document.id,
55
57
  message: 'Document ingested successfully and stored in PostgreSQL',
56
- totalDocuments
58
+ totalDocuments,
57
59
  };
58
60
  }
59
61
 
60
62
  async search(query: string, topK = 5) {
61
63
  const totalDocuments = await this.prisma.document.count();
62
64
  console.log(`RAG search requested for: "${query}". Total documents: ${totalDocuments}`);
63
-
65
+
64
66
  // Generate embedding for the query
65
67
  const queryVector = await this.embeddings.embed(query);
66
-
68
+
67
69
  // Perform vector similarity search using raw SQL for cosine similarity
68
70
  // Note: We don't select the embedding column to avoid deserialization issues
69
- const results = await this.prisma.$queryRaw<Array<{
70
- id: string;
71
- content: string;
72
- metadata: any;
73
- similarity: number;
74
- }>>`
71
+ const results = await this.prisma.$queryRaw<
72
+ Array<{
73
+ id: string;
74
+ content: string;
75
+ metadata: any;
76
+ similarity: number;
77
+ }>
78
+ >`
75
79
  SELECT
76
80
  id,
77
81
  content,
@@ -81,22 +85,22 @@ export class RAGService {
81
85
  ORDER BY embedding <=> ${queryVector}::vector
82
86
  LIMIT ${topK}
83
87
  `;
84
-
88
+
85
89
  console.log(`RAG search for "${query}" returned ${results.length} results`);
86
-
87
- return results.map(result => ({
90
+
91
+ return results.map((result) => ({
88
92
  id: result.id,
89
93
  content: result.content,
90
94
  score: result.similarity,
91
95
  metadata: result.metadata,
92
96
  }));
93
97
  }
94
-
98
+
95
99
  async getDocumentCount() {
96
100
  const totalDocuments = await this.prisma.document.count();
97
101
  return { totalDocuments };
98
102
  }
99
-
103
+
100
104
  async getAllDocuments() {
101
105
  const documents = await this.prisma.document.findMany({
102
106
  select: {
@@ -132,29 +136,29 @@ export class RAGController {
132
136
  @Get('documents')
133
137
  async getDocuments() {
134
138
  const stats = await this.ragService.getDocumentCount();
135
- return {
139
+ return {
136
140
  message: 'RAG service is ready - PostgreSQL vector store with persistent storage',
137
141
  ...stats,
138
142
  endpoints: {
139
143
  ingest: 'POST /rag/ingest - Add documents to PostgreSQL',
140
144
  search: 'POST /rag/search - Search documents with vector similarity',
141
145
  stats: 'GET /rag/stats - Get document count',
142
- list: 'GET /rag/list - List all documents'
143
- }
146
+ list: 'GET /rag/list - List all documents',
147
+ },
144
148
  };
145
149
  }
146
-
150
+
147
151
  @Get('stats')
148
152
  async getStats() {
149
153
  return this.ragService.getDocumentCount();
150
154
  }
151
-
155
+
152
156
  @Get('list')
153
157
  async listDocuments() {
154
158
  const documents = await this.ragService.getAllDocuments();
155
- return {
159
+ return {
156
160
  documents,
157
- total: documents.length
161
+ total: documents.length,
158
162
  };
159
163
  }
160
164
  }
package/README.md CHANGED
@@ -37,6 +37,7 @@ npm install --save-dev @hazeljs/cli
37
37
  ### Create a New Application
38
38
 
39
39
  **AI-Native Application (Recommended for AI Projects):**
40
+
40
41
  ```bash
41
42
  hazel g app my-ai-app --template=ai-native
42
43
  cd my-ai-app && npm install && cp .env.example .env && docker-compose up -d && npm run dev
@@ -45,17 +46,20 @@ cd my-ai-app && npm install && cp .env.example .env && docker-compose up -d && n
45
46
  Creates a complete AI-powered application with agents, RAG (PostgreSQL + pgvector), Redis, and Docker.
46
47
 
47
48
  **Skeleton app (quick start):**
49
+
48
50
  ```bash
49
51
  hazel g app my-app
50
52
  cd my-app && npm install && npm run dev
51
53
  ```
52
54
 
53
55
  **Full setup with interactive package selection:**
56
+
54
57
  ```bash
55
58
  hazel new my-app -i
56
59
  ```
57
60
 
58
61
  **Options:**
62
+
59
63
  - `-d, --dest <path>` - Destination path (default: current directory)
60
64
  - `-i, --interactive` - Interactive setup with package selection
61
65
  - `--template <template>` - Template to use (`ai-native` or `default`)
@@ -79,6 +83,7 @@ hazel add [package] [--setup] [--dev]
79
83
  Install a HazelJS package and show usage hints. Use `--setup` to also generate a minimal starter file.
80
84
 
81
85
  **Examples:**
86
+
82
87
  ```bash
83
88
  hazel add # Interactive package selection
84
89
  hazel add ai # Install @hazeljs/ai
@@ -95,46 +100,48 @@ hazel g <type> <name> [--path <path>] [--dry-run] [--json]
95
100
  ```
96
101
 
97
102
  **Discover generators:**
103
+
98
104
  ```bash
99
105
  hazel g --list # Human-readable list
100
106
  hazel g --list --list-json # JSON output
101
107
  ```
102
108
 
103
109
  **Common options** (work the same for every generator):
110
+
104
111
  - `-p, --path <path>` - Where to generate (default: `src`)
105
112
  - `--dry-run` - Preview files without writing them
106
113
  - `--json` - Output result as JSON (`{ ok, created, nextSteps }`)
107
114
 
108
115
  #### Multi-File Generators
109
116
 
110
- | Generator | Alias | Description | Creates |
111
- |-----------|-------|-------------|---------|
112
- | `crud <name>` | — | Complete CRUD resource | controller + service + module + DTOs |
113
- | `module <name>` | `m` | Feature module | module + controller + service + DTOs |
114
- | `dto <name>` | `d` | Create & update DTOs | two DTO files |
115
- | `auth` | — | Auth module | JWT guard + service + controller + DTOs |
117
+ | Generator | Alias | Description | Creates |
118
+ | --------------- | ----- | ---------------------- | --------------------------------------- |
119
+ | `crud <name>` | — | Complete CRUD resource | controller + service + module + DTOs |
120
+ | `module <name>` | `m` | Feature module | module + controller + service + DTOs |
121
+ | `dto <name>` | `d` | Create & update DTOs | two DTO files |
122
+ | `auth` | — | Auth module | JWT guard + service + controller + DTOs |
116
123
 
117
124
  #### Single-File Generators
118
125
 
119
- | Generator | Alias | Description |
120
- |-----------|-------|-------------|
121
- | `controller <name>` | `c` | REST controller with CRUD methods |
122
- | `service <name>` | `s` | Injectable service class |
123
- | `guard <name>` | `gu` | Route guard (e.g. auth) |
124
- | `interceptor <name>` | `i` | Request/response interceptor |
125
- | `middleware <name>` | `mw` | Express-style middleware |
126
- | `pipe <name>` | — | Validation/transform pipe |
127
- | `filter <name>` | `f` | Exception filter |
128
- | `repository <name>` | `repo` | Prisma repository |
129
- | `gateway <name>` | `ws` | WebSocket gateway |
130
- | `ai-service <name>` | `ai` | AI service with decorators |
131
- | `agent <name>` | — | AI agent with @Agent and @Tool |
132
- | `cache <name>` | — | Cache service with decorators |
133
- | `cron <name>` | `job` | Cron/scheduled job service |
134
- | `rag <name>` | — | RAG service |
135
- | `discovery <name>` | — | Service discovery setup |
136
- | `config` | — | Config module setup |
137
- | `serverless <name>` | `sls` | Serverless handler (Lambda/Cloud Function) |
126
+ | Generator | Alias | Description |
127
+ | -------------------- | ------ | ------------------------------------------ |
128
+ | `controller <name>` | `c` | REST controller with CRUD methods |
129
+ | `service <name>` | `s` | Injectable service class |
130
+ | `guard <name>` | `gu` | Route guard (e.g. auth) |
131
+ | `interceptor <name>` | `i` | Request/response interceptor |
132
+ | `middleware <name>` | `mw` | Express-style middleware |
133
+ | `pipe <name>` | — | Validation/transform pipe |
134
+ | `filter <name>` | `f` | Exception filter |
135
+ | `repository <name>` | `repo` | Prisma repository |
136
+ | `gateway <name>` | `ws` | WebSocket gateway |
137
+ | `ai-service <name>` | `ai` | AI service with decorators |
138
+ | `agent <name>` | — | AI agent with @Agent and @Tool |
139
+ | `cache <name>` | — | Cache service with decorators |
140
+ | `cron <name>` | `job` | Cron/scheduled job service |
141
+ | `rag <name>` | — | RAG service |
142
+ | `discovery <name>` | — | Service discovery setup |
143
+ | `config` | — | Config module setup |
144
+ | `serverless <name>` | `sls` | Serverless handler (Lambda/Cloud Function) |
138
145
 
139
146
  **Serverless** also accepts `--platform <lambda|cloud-function>` (default: `lambda`).
140
147
 
@@ -302,8 +309,9 @@ hazel g service users --json
302
309
  ```
303
310
 
304
311
  The manifest is automatically generated during build and always reflects the current package version. It includes:
312
+
305
313
  - Complete command schemas with options and arguments
306
- - All available generators with their capabilities
314
+ - All available generators with their capabilities
307
315
  - Package registry for `hazel add` commands
308
316
  - JSON schema validation for agent tool-use
309
317
 
@@ -316,4 +324,4 @@ Apache-2.0 © [HazelJS](https://hazeljs.ai)
316
324
  - [Documentation](https://hazeljs.ai/docs/packages/cli)
317
325
  - [GitHub](https://github.com/hazel-js/hazeljs)
318
326
  - [Issues](https://github.com/hazel-js/hazeljs/issues)
319
- - [Discord](https://discord.gg/PxNBPzvQk7)
327
+ - [Discord](https://discord.gg/PxNBPzvQk7)
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.7.9",
7
+ "version": "0.8.1",
8
8
  "description": "CLI for generating HazelJS components and applications"
9
9
  },
10
10
  "commands": [