@hazeljs/cli 2.0.0 → 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/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.0",
7
+ "version": "2.0.1",
8
8
  "description": "CLI for generating HazelJS components and applications"
9
9
  },
10
10
  "commands": [
@@ -874,6 +874,87 @@
874
874
  "description": "Display information about the current HazelJS project",
875
875
  "args": [],
876
876
  "options": []
877
+ },
878
+ {
879
+ "name": "store",
880
+ "usage": "hazel store <subcommand>",
881
+ "description": "Local Agent OS package registry (publish / install DNA packages)",
882
+ "subcommands": [
883
+ {
884
+ "name": "publish",
885
+ "usage": "hazel store publish <file> [--registry <dir>]",
886
+ "description": "Publish marketplace/DNA JSON to ~/.hazel/registry",
887
+ "args": [
888
+ {
889
+ "name": "file",
890
+ "type": "string",
891
+ "required": true,
892
+ "description": "Path to .dna.json or marketplace package JSON"
893
+ }
894
+ ],
895
+ "options": [
896
+ {
897
+ "name": "registry",
898
+ "type": "string",
899
+ "description": "Override registry root (default: ~/.hazel/registry)"
900
+ }
901
+ ]
902
+ },
903
+ {
904
+ "name": "install",
905
+ "usage": "hazel store install <spec> [--cwd <dir>] [--registry <dir>]",
906
+ "description": "Install package into project .hazel/agents (file path or name@version from local registry)",
907
+ "args": [
908
+ {
909
+ "name": "spec",
910
+ "type": "string",
911
+ "required": true,
912
+ "description": "File path or package name[@version]"
913
+ }
914
+ ],
915
+ "options": [
916
+ {
917
+ "name": "cwd",
918
+ "type": "string",
919
+ "default": ".",
920
+ "description": "Project root"
921
+ },
922
+ {
923
+ "name": "registry",
924
+ "type": "string",
925
+ "description": "Override registry root"
926
+ }
927
+ ]
928
+ },
929
+ {
930
+ "name": "list",
931
+ "usage": "hazel store list [query]",
932
+ "description": "List packages in the local registry"
933
+ },
934
+ {
935
+ "name": "remove",
936
+ "usage": "hazel store remove <name[@version]>",
937
+ "description": "Remove a package from the local registry"
938
+ },
939
+ {
940
+ "name": "doctor",
941
+ "usage": "hazel store doctor",
942
+ "description": "Check local registry health"
943
+ }
944
+ ]
945
+ },
946
+ {
947
+ "name": "install",
948
+ "usage": "hazel install <spec> [--cwd <dir>] [--registry <dir>]",
949
+ "description": "Alias for hazel store install",
950
+ "args": [
951
+ {
952
+ "name": "spec",
953
+ "type": "string",
954
+ "required": true,
955
+ "description": "File path or package name[@version]"
956
+ }
957
+ ]
877
958
  }
878
959
  ],
879
960
  "globalOptions": [
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Agent OS project templates for `hazel agent new`.
3
+ *
4
+ * DNA ≈ OpenAPI for agents (contract). App code = real tool implementations.
5
+ * `hazel agent run` on DNA alone uses stubs — production needs the app tools.
6
+ */
7
+ export type AgentTemplateId = 'bare' | 'agent-os' | 'skillgate';
8
+ export interface AgentTemplateMeta {
9
+ id: AgentTemplateId;
10
+ label: string;
11
+ description: string;
12
+ }
13
+ export declare const AGENT_TEMPLATES: AgentTemplateMeta[];
14
+ export declare function listAgentTemplates(): AgentTemplateMeta[];
15
+ export declare function resolveAgentTemplate(id: string): AgentTemplateId;
16
+ export interface ScaffoldAgentProjectOptions {
17
+ name: string;
18
+ destDir: string;
19
+ template: AgentTemplateId;
20
+ force?: boolean;
21
+ }
22
+ export interface ScaffoldAgentProjectResult {
23
+ path: string;
24
+ template: AgentTemplateId;
25
+ files: string[];
26
+ }
27
+ export declare function scaffoldAgentProject(options: ScaffoldAgentProjectOptions): ScaffoldAgentProjectResult;
@@ -0,0 +1,480 @@
1
+ "use strict";
2
+ /**
3
+ * Agent OS project templates for `hazel agent new`.
4
+ *
5
+ * DNA ≈ OpenAPI for agents (contract). App code = real tool implementations.
6
+ * `hazel agent run` on DNA alone uses stubs — production needs the app tools.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.AGENT_TEMPLATES = void 0;
43
+ exports.listAgentTemplates = listAgentTemplates;
44
+ exports.resolveAgentTemplate = resolveAgentTemplate;
45
+ exports.scaffoldAgentProject = scaffoldAgentProject;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ exports.AGENT_TEMPLATES = [
49
+ {
50
+ id: 'bare',
51
+ label: 'Bare DNA package',
52
+ description: 'Marketplace DNA only — publish/install/run with stub tools (packaging smoke)',
53
+ },
54
+ {
55
+ id: 'agent-os',
56
+ label: 'Agent OS mini-app',
57
+ description: 'DNA + real @Agent/@Tool TypeScript app (HITL refund demo) + store lock',
58
+ },
59
+ {
60
+ id: 'skillgate',
61
+ label: 'Skillgate concierge',
62
+ description: 'DNA + Skillgate fromOpenApi sample + register sketch for API concierge',
63
+ },
64
+ ];
65
+ function listAgentTemplates() {
66
+ return [...exports.AGENT_TEMPLATES];
67
+ }
68
+ function resolveAgentTemplate(id) {
69
+ const found = exports.AGENT_TEMPLATES.find((t) => t.id === id);
70
+ if (!found) {
71
+ throw new Error(`Unknown agent template "${id}". Available: ${exports.AGENT_TEMPLATES.map((t) => t.id).join(', ')}`);
72
+ }
73
+ return found.id;
74
+ }
75
+ function writeFile(root, rel, content) {
76
+ const full = path.join(root, rel);
77
+ fs.mkdirSync(path.dirname(full), { recursive: true });
78
+ fs.writeFileSync(full, content.endsWith('\n') ? content : content + '\n');
79
+ }
80
+ function sanitizeNpmName(name) {
81
+ return (name
82
+ .trim()
83
+ .toLowerCase()
84
+ .replace(/[^a-z0-9-_]/g, '-')
85
+ .replace(/^-+|-+$/g, '') || 'my-agent');
86
+ }
87
+ function agentDnaName(projectName) {
88
+ return sanitizeNpmName(projectName).replace(/-/g, '_').slice(0, 48) || 'my_agent';
89
+ }
90
+ function marketplacePackage(projectName, opts) {
91
+ const dnaName = agentDnaName(projectName);
92
+ const pkg = {
93
+ name: `@local/${sanitizeNpmName(projectName)}-agent`,
94
+ version: '1.0.0',
95
+ description: opts.description,
96
+ dna: {
97
+ format: 'hazeljs.agent.dna',
98
+ version: '1.0.0',
99
+ name: dnaName,
100
+ description: opts.description,
101
+ systemPrompt: opts.systemPrompt,
102
+ tools: opts.tools,
103
+ policies: opts.policies ?? [],
104
+ contracts: [{ name: `${dnaName}-slo`, maxLatencyMs: 30000 }],
105
+ exportedAt: new Date().toISOString(),
106
+ },
107
+ readme: opts.description,
108
+ keywords: opts.keywords,
109
+ };
110
+ return JSON.stringify(pkg, null, 2);
111
+ }
112
+ function bareFiles(projectName) {
113
+ const pkgJson = marketplacePackage(projectName, {
114
+ description: `${projectName} — DNA-only agent package`,
115
+ systemPrompt: `You are ${projectName}. Be concise. Use tools when available; otherwise explain what you would do.`,
116
+ tools: [
117
+ { name: 'ping', description: 'Health ping (stub in CLI run)' },
118
+ { name: 'echo', description: 'Echo input (stub in CLI run)' },
119
+ ],
120
+ keywords: ['agent-os', 'dna', 'bare'],
121
+ });
122
+ return {
123
+ 'package.json': JSON.stringify({
124
+ name: sanitizeNpmName(projectName),
125
+ version: '1.0.0',
126
+ private: true,
127
+ description: `DNA package for ${projectName}`,
128
+ scripts: {
129
+ 'agent:run': 'hazel agent run dna/agent.marketplace.json',
130
+ 'store:publish': 'hazel store publish dna/agent.marketplace.json',
131
+ 'store:install': 'hazel store install dna/agent.marketplace.json',
132
+ },
133
+ keywords: ['hazeljs', 'agent-os', 'dna'],
134
+ license: 'Apache-2.0',
135
+ }, null, 2),
136
+ 'dna/agent.marketplace.json': pkgJson,
137
+ 'README.md': `# ${projectName}
138
+
139
+ Bare **Agent DNA** package (contract only — like OpenAPI for an agent).
140
+
141
+ ## Commands
142
+
143
+ \`\`\`bash
144
+ # Smoke-run (Agent OS engine + stub tools + mock/real LLM)
145
+ npx hazel agent run dna/agent.marketplace.json "hello"
146
+
147
+ # Publish to local registry, then install into a project
148
+ npx hazel store publish dna/agent.marketplace.json
149
+ npx hazel store install @local/${sanitizeNpmName(projectName)}-agent --cwd /path/to/app
150
+ \`\`\`
151
+
152
+ ## Important
153
+
154
+ \`hazel agent run\` executes the **runtime** with **stub** tool handlers.
155
+ Wire real \`@Tool\` / Skillgate handlers in your Hazel app for production behavior.
156
+ `,
157
+ };
158
+ }
159
+ function agentOsFiles(projectName) {
160
+ const dnaName = agentDnaName(projectName);
161
+ const npm = sanitizeNpmName(projectName);
162
+ const marketplace = marketplacePackage(projectName, {
163
+ description: `${projectName} — Agent OS support-style agent with real tools`,
164
+ systemPrompt: `You are ${projectName}, a support desk agent.
165
+ Use lookupOrder for facts. Call processRefund only after lookup. Be concise.`,
166
+ tools: [
167
+ { name: 'lookupOrder', description: 'Look up an order by id' },
168
+ {
169
+ name: 'processRefund',
170
+ description: 'Process a refund (requires approval)',
171
+ requiresApproval: true,
172
+ },
173
+ ],
174
+ policies: [
175
+ {
176
+ id: 'refund-needs-approval',
177
+ tool: 'processRefund',
178
+ effect: 'require_approval',
179
+ priority: 20,
180
+ },
181
+ ],
182
+ keywords: ['agent-os', 'hitl', 'support'],
183
+ });
184
+ return {
185
+ 'package.json': JSON.stringify({
186
+ name: npm,
187
+ version: '1.0.0',
188
+ private: true,
189
+ description: `Agent OS mini-app: ${projectName}`,
190
+ scripts: {
191
+ build: 'tsc',
192
+ start: 'node dist/main.js',
193
+ dev: 'ts-node --transpile-only src/main.ts',
194
+ 'agent:run': 'hazel agent run dna/agent.marketplace.json',
195
+ 'store:publish': 'hazel store publish dna/agent.marketplace.json',
196
+ 'store:install': 'hazel store install dna/agent.marketplace.json --cwd .',
197
+ },
198
+ dependencies: {
199
+ '@hazeljs/agent': '^1.0.6',
200
+ 'reflect-metadata': '^0.2.2',
201
+ },
202
+ devDependencies: {
203
+ '@types/node': '^20.19.39',
204
+ 'ts-node': '^10.9.2',
205
+ typescript: '^5.9.3',
206
+ },
207
+ license: 'Apache-2.0',
208
+ }, null, 2),
209
+ 'tsconfig.json': JSON.stringify({
210
+ compilerOptions: {
211
+ target: 'ES2022',
212
+ module: 'commonjs',
213
+ outDir: 'dist',
214
+ rootDir: 'src',
215
+ strict: true,
216
+ esModuleInterop: true,
217
+ skipLibCheck: true,
218
+ experimentalDecorators: true,
219
+ emitDecoratorMetadata: true,
220
+ },
221
+ include: ['src/**/*'],
222
+ }, null, 2),
223
+ 'dna/agent.marketplace.json': marketplace,
224
+ 'src/orders.ts': `export type Order = { id: string; status: string; totalUsd: number };
225
+
226
+ const ORDERS: Record<string, Order> = {
227
+ 'ORD-1001': { id: 'ORD-1001', status: 'shipped', totalUsd: 128 },
228
+ 'ORD-1002': { id: 'ORD-1002', status: 'delivered', totalUsd: 64 },
229
+ };
230
+
231
+ export function getOrder(id: string): Order | undefined {
232
+ return ORDERS[id.toUpperCase()];
233
+ }
234
+ `,
235
+ 'src/support.agent.ts': `import 'reflect-metadata';
236
+ import { Agent, Tool } from '@hazeljs/agent';
237
+ import { getOrder } from './orders';
238
+
239
+ @Agent({
240
+ name: '${dnaName}',
241
+ description: '${projectName} support agent',
242
+ systemPrompt: \`You are ${projectName}. Use lookupOrder for facts. Use processRefund only after lookup.\`,
243
+ maxSteps: 8,
244
+ })
245
+ export class SupportAgent {
246
+ @Tool({
247
+ name: 'lookupOrder',
248
+ description: 'Look up an order by id (e.g. ORD-1001)',
249
+ parameters: [{ name: 'orderId', type: 'string', required: true }],
250
+ })
251
+ async lookupOrder({ orderId }: { orderId: string }) {
252
+ const order = getOrder(orderId);
253
+ if (!order) return { found: false, error: \`No order \${orderId}\` };
254
+ return { found: true, order };
255
+ }
256
+
257
+ @Tool({
258
+ name: 'processRefund',
259
+ description: 'Process a refund — requires human approval',
260
+ requiresApproval: true,
261
+ parameters: [
262
+ { name: 'orderId', type: 'string', required: true },
263
+ { name: 'amount', type: 'number', required: true },
264
+ ],
265
+ })
266
+ async processRefund({ orderId, amount }: { orderId: string; amount: number }) {
267
+ const order = getOrder(orderId);
268
+ if (!order) return { ok: false, error: \`No order \${orderId}\` };
269
+ return { ok: true, orderId: order.id, amount, status: 'refunded' };
270
+ }
271
+ }
272
+ `,
273
+ 'src/main.ts': `/**
274
+ * Mini Agent OS app — real tools (not DNA stubs).
275
+ * DNA in dna/ can be hot-reloaded / store-installed for prompt+policy overlays.
276
+ */
277
+ import 'reflect-metadata';
278
+ import {
279
+ AgentRuntime,
280
+ AgentEventType,
281
+ createMockLlmProvider,
282
+ type AgentEvent,
283
+ } from '@hazeljs/agent';
284
+ import { SupportAgent } from './support.agent';
285
+
286
+ async function main() {
287
+ const input = process.argv.slice(2).join(' ') || 'Where is ORD-1001?';
288
+ // Demo uses mock LLM. Wire OpenAI (or another provider) in production apps.
289
+ const llm = createMockLlmProvider(
290
+ 'Used real @Tool handlers on AgentRuntime. (Replace createMockLlmProvider with your LLM.)'
291
+ );
292
+
293
+ const runtime = new AgentRuntime({
294
+ llmProvider: llm,
295
+ enableRetry: false,
296
+ enableCircuitBreaker: false,
297
+ });
298
+
299
+ runtime.registerAgent(SupportAgent);
300
+ runtime.registerAgentInstance('${dnaName}', new SupportAgent());
301
+
302
+ // Auto-approve refunds unless HITL=1
303
+ if (process.env.HITL !== '1') {
304
+ runtime.on(AgentEventType.TOOL_APPROVAL_REQUESTED, (event) => {
305
+ const data = (event as AgentEvent<{ requestId?: string }>).data;
306
+ if (data?.requestId) runtime.approveToolExecution(data.requestId, 'demo');
307
+ });
308
+ }
309
+
310
+ // DNA file is for store publish/install + CLI smoke.
311
+ // Do not installAgentPackage here if it would re-register tools without handlers.
312
+ // Use DNA overlay for prompt/policies in production only when tools are wired.
313
+
314
+ const result = await runtime.execute('${dnaName}', input, { maxSteps: 8 });
315
+ console.log(JSON.stringify({ response: result.response, state: result.state, steps: result.steps.length }, null, 2));
316
+ }
317
+
318
+ main().catch((e) => {
319
+ console.error(e);
320
+ process.exit(1);
321
+ });
322
+ `,
323
+ 'README.md': `# ${projectName}
324
+
325
+ **Agent OS mini-app** — DNA contract + **real** \`@Tool\` implementations.
326
+
327
+ | Path | Role |
328
+ | --- | --- |
329
+ | \`dna/agent.marketplace.json\` | DNA / marketplace package (OpenAPI-for-agents) |
330
+ | \`src/support.agent.ts\` | Real tool handlers |
331
+ | \`src/main.ts\` | AgentRuntime bootstrap + optional DNA overlay |
332
+
333
+ ## Quick start
334
+
335
+ \`\`\`bash
336
+ npm install
337
+ npm run dev
338
+ npm run dev -- I want a refund for ORD-1002
339
+
340
+ # DNA smoke (stubs — not the same as npm run dev)
341
+ npx hazel agent run dna/agent.marketplace.json "hello"
342
+
343
+ # Package+Store
344
+ npm run store:publish
345
+ npm run store:install
346
+ \`\`\`
347
+
348
+ Set \`HITL=1\` to pause on \`processRefund\` approvals.
349
+ `,
350
+ };
351
+ }
352
+ function skillgateFiles(projectName) {
353
+ const npm = sanitizeNpmName(projectName);
354
+ const marketplace = marketplacePackage(projectName, {
355
+ description: `${projectName} — API concierge (Skillgate-governed REST skills)`,
356
+ systemPrompt: `You are an API concierge. Prefer read skills first. Writes need approval.`,
357
+ tools: [
358
+ { name: 'getOrder', description: 'GET order by id (Skillgate read)' },
359
+ {
360
+ name: 'createRefund',
361
+ description: 'POST refund (Skillgate write + approval)',
362
+ requiresApproval: true,
363
+ },
364
+ ],
365
+ keywords: ['skillgate', 'agent-os', 'openapi'],
366
+ });
367
+ return {
368
+ 'package.json': JSON.stringify({
369
+ name: npm,
370
+ version: '1.0.0',
371
+ private: true,
372
+ description: `Skillgate agent starter: ${projectName}`,
373
+ scripts: {
374
+ build: 'tsc',
375
+ report: 'ts-node --transpile-only src/report.ts',
376
+ 'agent:run': 'hazel agent run dna/agent.marketplace.json',
377
+ 'store:publish': 'hazel store publish dna/agent.marketplace.json',
378
+ },
379
+ dependencies: {
380
+ '@hazeljs/agent': '^1.0.6',
381
+ '@hazeljs/skillgate': '^1.0.6',
382
+ },
383
+ devDependencies: {
384
+ '@types/node': '^20.19.39',
385
+ 'ts-node': '^10.9.2',
386
+ typescript: '^5.9.3',
387
+ },
388
+ license: 'Apache-2.0',
389
+ }, null, 2),
390
+ 'tsconfig.json': JSON.stringify({
391
+ compilerOptions: {
392
+ target: 'ES2022',
393
+ module: 'commonjs',
394
+ outDir: 'dist',
395
+ rootDir: 'src',
396
+ strict: true,
397
+ esModuleInterop: true,
398
+ skipLibCheck: true,
399
+ },
400
+ include: ['src/**/*'],
401
+ }, null, 2),
402
+ 'dna/agent.marketplace.json': marketplace,
403
+ 'openapi/sample.openapi.json': JSON.stringify({
404
+ openapi: '3.0.3',
405
+ info: { title: `${projectName} API`, version: '1.0.0' },
406
+ servers: [{ url: 'http://127.0.0.1:3000' }],
407
+ paths: {
408
+ '/orders/{id}': {
409
+ get: {
410
+ operationId: 'getOrder',
411
+ tags: ['agent'],
412
+ summary: 'Fetch an order by id',
413
+ parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
414
+ 'x-hazel-skill': { readOnly: true, class: 'read' },
415
+ },
416
+ },
417
+ '/refunds': {
418
+ post: {
419
+ operationId: 'createRefund',
420
+ tags: ['agent'],
421
+ summary: 'Create a refund',
422
+ 'x-hazel-skill': { requiresApproval: true, class: 'write' },
423
+ },
424
+ },
425
+ },
426
+ }, null, 2),
427
+ 'src/report.ts': `import * as fs from 'fs';
428
+ import * as path from 'path';
429
+ import { Skillgate, type OpenApiLike } from '@hazeljs/skillgate';
430
+ import { ToolRegistry } from '@hazeljs/agent';
431
+
432
+ const specPath = path.join(__dirname, '..', 'openapi', 'sample.openapi.json');
433
+ const spec = JSON.parse(fs.readFileSync(specPath, 'utf8')) as OpenApiLike;
434
+
435
+ const gate = Skillgate.fromOpenApi(spec, {
436
+ include: { tags: ['agent'] },
437
+ classify: { writeRequiresApproval: true },
438
+ invoke: { baseUrl: process.env.API_BASE_URL || 'http://127.0.0.1:3000' },
439
+ });
440
+
441
+ const registry = new ToolRegistry();
442
+ gate.register(registry, 'api-concierge');
443
+
444
+ console.log(JSON.stringify(gate.report(), null, 2));
445
+ console.log('Registered tools:', registry.getAgentTools('api-concierge').map((t) => t.name));
446
+ `,
447
+ 'README.md': `# ${projectName}
448
+
449
+ **Skillgate** starter — OpenAPI → governed agent skills + DNA package.
450
+
451
+ \`\`\`bash
452
+ npm install
453
+ npm run report # Skillgate included/denied report
454
+ npx hazel agent run dna/agent.marketplace.json
455
+ npx hazel store publish dna/agent.marketplace.json
456
+ \`\`\`
457
+
458
+ See also: full showcase \`hazeljs-skillgate-agent-starter\` in the monorepo.
459
+ `,
460
+ };
461
+ }
462
+ function scaffoldAgentProject(options) {
463
+ const template = resolveAgentTemplate(options.template);
464
+ const root = path.resolve(options.destDir);
465
+ if (fs.existsSync(root) && fs.readdirSync(root).length > 0 && !options.force) {
466
+ throw new Error(`Destination not empty: ${root} (pass force to overwrite)`);
467
+ }
468
+ const files = template === 'bare'
469
+ ? bareFiles(options.name)
470
+ : template === 'skillgate'
471
+ ? skillgateFiles(options.name)
472
+ : agentOsFiles(options.name);
473
+ fs.mkdirSync(root, { recursive: true });
474
+ const written = [];
475
+ for (const [rel, content] of Object.entries(files)) {
476
+ writeFile(root, rel, content);
477
+ written.push(rel);
478
+ }
479
+ return { path: root, template, files: written };
480
+ }
@@ -1,7 +1,9 @@
1
1
  import { Command } from 'commander';
2
2
  /**
3
+ * `hazel agent new` — scaffold Agent OS / DNA templates (G2 template unification).
3
4
  * `hazel agent install <file.dna.json>` — validate / print marketplace install plan.
4
5
  * `hazel agent run` — live execute from DNA (AOS-011).
6
+ * `hazel agent apply|get|describe|delete|reconcile|events` — declarative platform resources (local control plane).
5
7
  * `hazel agent logs` / `doctor` — timeline + environment checks.
6
8
  * `hazel agent runs list|inspect|cancel|resume|approve` — durable store ops.
7
9
  */