naider 1.19.0 → 1.21.0

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/README.md CHANGED
@@ -77,6 +77,9 @@ naide pkg install <name> # Install a NAIDE package
77
77
  naide pkg publish # Publish package to npm
78
78
  naide -w <file> # Watch mode (auto-restart on changes)
79
79
  naide -d <file> # Debug mode (Node.js inspector)
80
+ naide ~~ "instruction" # Generate NAIDE code from natural language
81
+ naide gen "instruction" # Same as ~~ (alias)
82
+ naide --expand <file> # Show ~~ directive expansion results
80
83
  naide --emit <file> # Print generated JavaScript
81
84
  naide -o <out.js> <file> # Write JavaScript to file
82
85
  naide --mid <file.nx> # Show intermediate NAIDE v1 (debug X mode)
@@ -84,11 +87,80 @@ naide --ast <file> # Print AST
84
87
  naide --tokens <file> # Print token stream
85
88
  ```
86
89
 
90
+ ### Code Generation (`~~`)
91
+
92
+ Generate valid NAIDE code from natural language instructions — no AI, no network, no dependencies. Pure pattern matching + template composition with self-healing parser validation. Multi-entity support with automatic relationship detection, paginated CRUD, soft delete, batch operations, nested routes, seed data, tests, and full project scaffolding.
93
+
94
+ ```bash
95
+ # Single entity
96
+ naide ~~ "REST API for users with auth"
97
+ naide ~~ "todo app with database"
98
+
99
+ # Multi-entity (auto-detects relationships, injects foreign keys)
100
+ naide ~~ "users and products and orders with auth"
101
+
102
+ # Composite presets
103
+ naide ~~ "shop" # User + Product + Order
104
+ naide ~~ "crm" # User + Contact + Deal + Activity
105
+ naide ~~ "sns" # User + Post + Comment + Message + Notification
106
+ naide ~~ "booking" # User + Event + Reservation
107
+
108
+ # Project mode (generates full directory)
109
+ naide ~~ "e-commerce app with auth" --project
110
+
111
+ # File write mode (merge into existing file)
112
+ naide ~~ "REST API for users" --write app.naide
113
+
114
+ # Japanese
115
+ naide ~~ "ECサイト"
116
+ naide ~~ "ユーザー管理APIを認証付きで"
117
+ ```
118
+
119
+ Generated routes per entity: paginated list, CRUD, soft delete, restore, batch create/delete, nested routes (from relationships), file upload, webhooks. With auth: register, login, profile, admin stats, audit log.
120
+
121
+ Project mode (`--project`) generates: `app.naide`, `package.json`, `.env`, `Dockerfile`, `README.md`, `openapi.json`, `admin.html`, `client.mjs`.
122
+
123
+ API usage:
124
+
125
+ ```javascript
126
+ import { generate, generateProject } from 'naider';
127
+
128
+ const result = generate("users and products with auth");
129
+ console.log(result.entities); // ['User', 'Product']
130
+ console.log(result.relationships); // [{parent:'User', child:'Product', fk:'user_id'}]
131
+ console.log(result.valid); // true
132
+ console.log(result.analysis); // {entities, relationships, plan, ...}
133
+
134
+ const project = generateProject("e-commerce with auth");
135
+ project.files.forEach(f => console.log(f.path));
136
+ ```
137
+
138
+ **Self-healing**: Generated code is validated against the actual NAIDE parser. Parse errors are auto-fixed (up to 5 retries) — missing colons, indent issues, reserved keyword conflicts.
139
+
140
+ **Field normalization**: Smart aliases — `e-mail` → `email`, `pwd` → `password`, `tel` → `phone`, `desc` → `description`. Field types are auto-inferred from names (`email` → `str + email`, `age` → `int`, `done` → `bool`).
141
+
142
+ <details>
143
+ <summary>Keyword Cheat Sheet</summary>
144
+
145
+ | Category | Keywords |
146
+ |----------|----------|
147
+ | Intent | `server` `api` `rest` `bot` `cli` `page` `test` `database` `ai` `crud` `auth` `websocket` `mail` `graphql` |
148
+ | Composite | `todo` `blog` `chat` `shop` `fullstack` `board` `crm` `inventory` `booking` `sns` |
149
+ | Platform | `discord` `slack` `telegram` `line` |
150
+ | DB Type | `sqlite` `postgres` |
151
+ | JP Intent | `サーバー` `認証` `ログイン` `会員` `CRUD` `管理` `データベース` `ボット` `テスト` `ページ` `メール` |
152
+ | JP Entity | `ユーザー` `商品` `記事` `タスク` `注文` `コメント` `イベント` `問い合わせ` `通知` `カテゴリ` `掲示板` `決済` `予約` `社員` |
153
+ | JP Composite | `管理システム` `やることリスト` `ブログ` `チャットアプリ` `ECサイト` `掲示板` |
154
+ | NL Phrases | `"users can comment"` `"admin manage"` `"upload"` `"search"` `"notification"` `"deploy"` `"seed"` |
155
+ | Fields | `"with name email age"` — auto-inferred types & validators |
156
+
157
+ </details>
158
+
87
159
  ### REPL
88
160
 
89
161
  ```
90
162
  $ naide
91
- NAIDE REPL v1.11.0 — type NAIDE code, see JavaScript output
163
+ NAIDE REPL v1.21.0 — type NAIDE code, see JavaScript output
92
164
  Type .exit to quit, .eval to toggle eval mode
93
165
 
94
166
  >>> str name = "hello"
package/bin/naide.js CHANGED
@@ -8,6 +8,42 @@ import { spawn } from 'child_process';
8
8
  import { createRequire } from 'module';
9
9
  const _require = createRequire(import.meta.url);
10
10
 
11
+ const NAIDE_VERSION = '1.21.0';
12
+
13
+ function crashReport(err, context = {}) {
14
+ const info = [
15
+ `NAIDE v${NAIDE_VERSION}`,
16
+ `Node ${process.version}`,
17
+ `${process.platform} ${process.arch}`,
18
+ ];
19
+ if (context.file) info.push(`File: ${context.file}`);
20
+ if (context.target) info.push(`Target: ${context.target}`);
21
+
22
+ console.error(`\n ┌─ NAIDE Internal Error ───────────────────────────`);
23
+ console.error(` │ ${err.message}`);
24
+ console.error(` │`);
25
+ console.error(` │ ${info.join(' | ')}`);
26
+ if (err.stack) {
27
+ const frames = err.stack.split('\n').slice(1, 4).map(l => l.trim());
28
+ for (const f of frames) console.error(` │ ${f}`);
29
+ }
30
+ console.error(` │`);
31
+ console.error(` │ This is a compiler bug, not a syntax error.`);
32
+ console.error(` │ Report: https://github.com/irxk/naide/issues/new`);
33
+ console.error(` │ Include the .naide file and the info above.`);
34
+ console.error(` └──────────────────────────────────────────────────\n`);
35
+ }
36
+
37
+ process.on('uncaughtException', (err) => {
38
+ crashReport(err);
39
+ process.exit(99);
40
+ });
41
+
42
+ process.on('unhandledRejection', (reason) => {
43
+ crashReport(reason instanceof Error ? reason : new Error(String(reason)));
44
+ process.exit(99);
45
+ });
46
+
11
47
  function checkDependencies(jsCode) {
12
48
  const depMap = {
13
49
  "from 'express'": { pkg: 'express', reason: 'server' },
@@ -77,6 +113,10 @@ const flags = {
77
113
  debug: false,
78
114
  check: false,
79
115
  target: 'node',
116
+ expand: false,
117
+ project: false,
118
+ write: null,
119
+ replace: false,
80
120
  };
81
121
 
82
122
  const files = [];
@@ -95,10 +135,198 @@ for (let i = 0; i < args.length; i++) {
95
135
  case '--debug': case '-d': flags.debug = true; break;
96
136
  case '--check': flags.check = true; flags.run = false; break;
97
137
  case '--target': case '-t': flags.target = args[++i]; break;
138
+ case '--expand': flags.expand = true; flags.run = false; break;
139
+ case '--project': case '-p': flags.project = true; break;
140
+ case '--write': flags.write = args[++i]; break;
141
+ case '--replace': flags.replace = true; break;
98
142
  default: files.push(arg);
99
143
  }
100
144
  }
101
145
 
146
+ // ── Code Generator (~~) ──
147
+ if (files[0] === 'gen' || files[0] === '~~') {
148
+ const instruction = files.slice(1).join(' ');
149
+ if (!instruction) {
150
+ console.log(`
151
+ NAIDE Agent Coder (~~)
152
+
153
+ Usage:
154
+ naide ~~ "REST API for users with auth"
155
+ naide gen "todo app with database"
156
+ naide gen "users and products and orders with auth"
157
+ naide ~~ "ECサイト" --project
158
+
159
+ Autonomous code generator with analysis, multi-entity support,
160
+ relationship detection, and full auth routes. No AI, no network.
161
+
162
+ Examples:
163
+ naide ~~ "REST API for products with name price stock"
164
+ naide ~~ "users and products with auth" # multi-entity
165
+ naide ~~ "SNS app" # User+Post+Comment
166
+ naide ~~ "ECサイト" # User+Product+Order
167
+ naide ~~ "予約システム" # User+Reservation
168
+ naide ~~ "Discord bot with hello and help commands"
169
+ naide ~~ "ユーザーと商品と注文の管理APIを認証付きで" # JP multi-entity
170
+
171
+ Project Mode (--project):
172
+ naide ~~ "e-commerce app with auth" --project
173
+ # Creates: app.naide, package.json, .env, .gitignore,
174
+ # Dockerfile, .dockerignore, README.md
175
+
176
+ File Write Mode:
177
+ naide ~~ "add auth" app.naide # merge into existing file
178
+ naide ~~ "add websocket" --write app.naide # explicit --write
179
+ naide ~~ "REST API" --write app.naide --replace # overwrite file
180
+
181
+ In .naide files:
182
+ ~~ "REST API for users with auth"
183
+ # Expands at compile time to full NAIDE code
184
+
185
+ Debug:
186
+ naide --expand app.naide Show ~~ expansion results
187
+
188
+ API:
189
+ import { generate, generateProject, writeToFile } from 'naider';
190
+ const result = generate("users and products with auth");
191
+ console.log(result.analysis); // agent analysis
192
+ console.log(result.entities); // ['User', 'Product']
193
+ writeToFile("app.naide", "add auth"); // merge into file
194
+
195
+ ── Keyword Cheat Sheet ──────────────────────────────────────
196
+
197
+ Intent server, api, rest, bot, cli, page, test, database,
198
+ ai, crud, auth, websocket, mail, graphql
199
+ Composite todo, blog, chat, shop, fullstack, board,
200
+ crm, inventory, booking, sns
201
+ Platform discord, slack, telegram, line
202
+ DB Type sqlite, postgres
203
+ JP Intent サーバー, 認証, ログイン, 会員, CRUD, 管理, データベース,
204
+ ボット, テスト, ページ, メール, リアルタイム
205
+ JP Entity ユーザー, 商品, 記事, タスク, 注文, コメント, イベント,
206
+ 問い合わせ, 通知, カテゴリ, プロジェクト, 掲示板, 決済
207
+ Fields "with name email age" — auto-inferred types & validators
208
+ Field Alias e-mail→email, pwd→password, tel→phone, desc→description
209
+ Relations Auto-detected: User→Post, User→Order, Product→Order, etc.
210
+
211
+ ────────────────────────────────────────────────────────────
212
+ `);
213
+ process.exit(0);
214
+ }
215
+
216
+ const { generate, generateProject, writeToFile } = await import('../src/gen.js');
217
+
218
+ // Write mode: inject into existing .naide/.nx file
219
+ const targetFile = instruction.match(/\S+\.(?:naide|nx)$/)?.[0];
220
+ if (targetFile || flags.write) {
221
+ const file = flags.write || targetFile;
222
+ const cleanInstruction = targetFile ? instruction.replace(/\s+\S+\.(?:naide|nx)$/, '') : instruction;
223
+ const mode = flags.replace ? 'replace' : 'append';
224
+ const result = writeToFile(resolve(file), cleanInstruction, { mode });
225
+ const a = result.analysis;
226
+ process.stderr.write('\n ── NAIDE Agent ──────────────────────────────────────────\n');
227
+ process.stderr.write(` Input: "${a.instruction}"\n`);
228
+ process.stderr.write(` Action: ${result.action} → ${file}\n`);
229
+ if (a.entities.length > 0) {
230
+ process.stderr.write(` Entities: ${a.entities.map(e => `${e.name} (${e.fieldCount} fields)`).join(', ')}\n`);
231
+ }
232
+ process.stderr.write(' ────────────────────────────────────────────────────────\n\n');
233
+ console.log(result.code);
234
+ process.stderr.write(` ── ${result.action}: ${file} (valid: ${result.valid}) ──\n`);
235
+ process.exit(0);
236
+ }
237
+
238
+ // Project mode: generate full project directory
239
+ if (flags.project) {
240
+ const result = generateProject(instruction);
241
+ const primaryName = (result.entities[0] || 'app').toLowerCase().replace(/[^a-z0-9]/g, '');
242
+ const dir = flags.output || (primaryName + '-app');
243
+ const outDir = resolve(dir);
244
+ if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
245
+ for (const f of result.files) {
246
+ const fp = resolve(outDir, f.path);
247
+ writeFileSync(fp, f.content, 'utf-8');
248
+ }
249
+ const a = result.analysis;
250
+ process.stderr.write('\n ── NAIDE Agent ──────────────────────────────────────────\n');
251
+ process.stderr.write(` Input: "${a.instruction}"\n`);
252
+ if (a.entities.length > 0) {
253
+ process.stderr.write(` Entities: ${a.entities.map(e => `${e.name} (${e.fieldCount} fields)`).join(', ')}\n`);
254
+ }
255
+ if (a.relationships.length > 0) {
256
+ for (const r of a.relationships) process.stderr.write(` Relation: ${r.parent} 1→N ${r.child} (${r.fk})\n`);
257
+ }
258
+ process.stderr.write(` Plan:\n`);
259
+ for (const step of a.plan) process.stderr.write(` + ${step}\n`);
260
+ process.stderr.write(' ────────────────────────────────────────────────────────\n\n');
261
+ console.log(` Project created: ${dir}/`);
262
+ for (const f of result.files) console.log(` ${f.path}`);
263
+ console.log(`\n cd ${dir} && npm install && npm run dev\n`);
264
+ process.exit(0);
265
+ }
266
+
267
+ const result = generate(instruction);
268
+
269
+ if (flags.output) {
270
+ writeFileSync(flags.output, result.code, 'utf-8');
271
+ console.log(` Generated: ${flags.output} (${result.intents.join(' + ')})`);
272
+ } else {
273
+ // Agent-style analysis header
274
+ const a = result.analysis;
275
+ process.stderr.write('\n ── NAIDE Agent ──────────────────────────────────────────\n');
276
+ process.stderr.write(` Input: "${a.instruction}"\n`);
277
+ if (a.entities.length > 0) {
278
+ process.stderr.write(` Entities: ${a.entities.map(e => `${e.name} (${e.fieldCount} fields)`).join(', ')}\n`);
279
+ }
280
+ if (a.relationships.length > 0) {
281
+ for (const r of a.relationships) {
282
+ process.stderr.write(` Relation: ${r.parent} 1→N ${r.child} (${r.fk})\n`);
283
+ }
284
+ }
285
+ process.stderr.write(` Plan:\n`);
286
+ for (const step of a.plan) {
287
+ process.stderr.write(` + ${step}\n`);
288
+ }
289
+ process.stderr.write(' ────────────────────────────────────────────────────────\n\n');
290
+
291
+ console.log(result.code);
292
+
293
+ const meta = [`[${result.intents.join(' + ')}]`];
294
+ if (result.entities && result.entities.length > 1) {
295
+ meta.push(`→ ${result.entities.join(', ')}`);
296
+ } else if (result.schema) {
297
+ meta.push(`→ ${result.schema}`);
298
+ }
299
+ meta.push(`valid: ${result.valid}`);
300
+ if (result.fixed) meta.push('(auto-fixed)');
301
+ process.stderr.write(` ── gen ~~ ${meta.join(' ')} ──\n`);
302
+ if (result.repairs.length > 0) {
303
+ process.stderr.write(' Repairs:\n');
304
+ for (const r of result.repairs) process.stderr.write(` - ${r}\n`);
305
+ }
306
+ if (result.suggestion) {
307
+ process.stderr.write(`\n${result.suggestion}\n`);
308
+ }
309
+ }
310
+ process.exit(0);
311
+ }
312
+
313
+ // ── Expand Debug ──
314
+ if (flags.expand && files.length > 0) {
315
+ const { expandDirectives } = await import('../src/gen.js');
316
+ for (const file of files) {
317
+ const filePath = resolve(file);
318
+ const source = readFileSync(filePath, 'utf-8');
319
+ const { source: expanded, expanded: didExpand } = expandDirectives(source);
320
+ if (didExpand) {
321
+ console.log(` ── ${file} (expanded) ──\n`);
322
+ console.log(expanded);
323
+ } else {
324
+ console.log(` ${file}: no ~~ directives found`);
325
+ }
326
+ }
327
+ process.exit(0);
328
+ }
329
+
102
330
  // ── VS Code Extension Install ──
103
331
  if (files[0] === 'vscode') {
104
332
  const os = await import('os');
@@ -357,24 +585,67 @@ if (files[0] === 'build') {
357
585
 
358
586
  console.log(`\n NAIDE build — ${sourceFiles.length} file(s)\n`);
359
587
  let errors = 0;
588
+ const schemaMap = {};
589
+ const routeMap = {};
590
+
360
591
  for (const srcFile of sourceFiles) {
361
592
  const rel = relative(dir, srcFile);
362
593
  const mode = srcFile.endsWith('.nx') ? 'x' : 'naide';
363
594
  try {
364
595
  const source = readFileSync(srcFile, 'utf-8');
365
- const { js } = compile(source, { mode });
596
+ const { js, ast } = compile(source, { mode });
366
597
  const outName = rel.replace(/\.(naide|nx)$/, '.mjs');
367
598
  const outPath = outDir ? join(outDir, outName) : join(dir, outName);
368
599
  const outDirPath = resolve(outPath, '..');
369
600
  if (!existsSync(outDirPath)) mkdirSync(outDirPath, { recursive: true });
370
601
  writeFileSync(outPath, js);
371
602
  console.log(` ${rel} → ${outDir ? join(relative('.', outDir), outName) : outName}`);
603
+
604
+ if (ast && ast.body) {
605
+ for (const node of ast.body) {
606
+ if (node.type === 'SchemaDecl' && node.name) {
607
+ (schemaMap[node.name] = schemaMap[node.name] || []).push(rel);
608
+ }
609
+ if (node.type === 'Server' && node.routes) {
610
+ for (const s of node.routes) {
611
+ if (s.type === 'CrudDecl' && s.path) {
612
+ const key = `CRUD ${s.path.raw || s.path}`;
613
+ (routeMap[key] = routeMap[key] || []).push(rel);
614
+ }
615
+ if (s.type === 'Route' && s.path) {
616
+ const key = `${(s.method || 'get').toUpperCase()} ${s.path.raw || s.path}`;
617
+ (routeMap[key] = routeMap[key] || []).push(rel);
618
+ }
619
+ }
620
+ }
621
+ }
622
+ }
372
623
  } catch (e) {
373
- console.error(` FAIL ${rel}: ${e.message.split('\n')[0]}`);
624
+ const isSyntaxErr = e.message.includes('line ') || e.message.includes('Unexpected') || e.message.includes('Expected');
625
+ if (isSyntaxErr) {
626
+ console.error(` FAIL ${rel}: ${e.message.split('\n')[0]}`);
627
+ } else {
628
+ crashReport(e, { file: rel });
629
+ }
374
630
  errors++;
375
631
  }
376
632
  }
377
- console.log(`\n Done. ${sourceFiles.length - errors} compiled, ${errors} failed.`);
633
+
634
+ let warnings = 0;
635
+ for (const [name, files] of Object.entries(schemaMap)) {
636
+ if (files.length > 1) {
637
+ console.error(` WARN: schema "${name}" defined in ${files.length} files: ${files.join(', ')}`);
638
+ warnings++;
639
+ }
640
+ }
641
+ for (const [route, files] of Object.entries(routeMap)) {
642
+ if (files.length > 1) {
643
+ console.error(` WARN: route ${route} defined in ${files.length} files: ${files.join(', ')}`);
644
+ warnings++;
645
+ }
646
+ }
647
+
648
+ console.log(`\n Done. ${sourceFiles.length - errors} compiled, ${errors} failed${warnings > 0 ? `, ${warnings} warning(s)` : ''}.`);
378
649
  process.exit(errors > 0 ? 1 : 0);
379
650
  }
380
651
 
@@ -664,6 +935,8 @@ if (flags.help) {
664
935
  naide Start interactive REPL
665
936
  naide <file.naide> Run a NAIDE file
666
937
  naide <file.nx> Run a NAIDE-X file (auto-detected)
938
+ naide ~~ "instruction" Generate NAIDE code from instruction (no AI)
939
+ naide gen "instruction" Same as ~~ (alias)
667
940
  naide init [dir] Create a new NAIDE project
668
941
  naide build [dir] [outdir] Transpile all files to JavaScript
669
942
  naide check <files...> Type-check without running
@@ -683,10 +956,28 @@ if (flags.help) {
683
956
  naide -w <file.naide> Watch mode (auto-restart on changes)
684
957
  naide -d <file> Debug mode (Node.js inspector)
685
958
 
686
- Targets:
959
+ Code Generation (~~):
960
+ naide ~~ "instruction" Generate code from instruction (no AI)
961
+ naide gen "instruction" Alias for ~~
962
+ naide --expand <file> Show ~~ directive expansion results
963
+ In .naide files: ~~ "instruction" expands at compile time
964
+
965
+ Targets (15):
687
966
  node Node.js / JavaScript (default)
688
967
  bun Bun-optimized JavaScript
689
- python Python (Flask for servers)
968
+ ts TypeScript
969
+ python Python (Flask)
970
+ go Go (net/http)
971
+ java Java (HttpServer)
972
+ rust Rust (actix-web)
973
+ cpp C++ (cpp-httplib)
974
+ c C (libmicrohttpd)
975
+ csharp C# (ASP.NET)
976
+ kotlin Kotlin (Ktor)
977
+ swift Swift (Vapor)
978
+ dart Dart (shelf)
979
+ php PHP
980
+ ruby Ruby (Sinatra)
690
981
 
691
982
  Modes:
692
983
  .naide Standard NAIDE (~40% fewer tokens than JS)
@@ -701,9 +992,18 @@ if (flags.help) {
701
992
  -t, --target Compile target: node (default), bun, python/py
702
993
  --check Type-check files without running
703
994
  --mid Show intermediate NAIDE v1 (X mode only)
995
+ --expand Show ~~ directive expansion (debug)
704
996
  --ast Print AST
705
997
  --tokens Print tokens
706
998
  -h, --help Show this help
999
+
1000
+ ~~ Keyword Cheat Sheet:
1001
+ Intent server api rest bot cli page test database ai crud auth ws mail graphql
1002
+ Composite todo blog chat shop fullstack board
1003
+ Platform discord slack telegram line
1004
+ JP Intent サーバー 認証 ログイン 会員 CRUD 管理 データベース ボット テスト ページ
1005
+ JP Entity ユーザー 商品 記事 タスク 注文 コメント イベント 問い合わせ 掲示板 決済
1006
+ Fields "with name email age done" → auto-inferred types
707
1007
  `);
708
1008
  process.exit(0);
709
1009
  }
@@ -872,7 +1172,12 @@ for (const file of files) {
872
1172
  } catch {}
873
1173
  }
874
1174
  } catch (err) {
875
- console.error(`\n${err.message}`);
1175
+ const isSyntaxErr = err.message.includes('line ') || err.message.includes('Unexpected') || err.message.includes('Expected');
1176
+ if (isSyntaxErr) {
1177
+ console.error(`\n${err.message}`);
1178
+ } else {
1179
+ crashReport(err, { file, target: flags.target });
1180
+ }
876
1181
  if (process.env.NAIDE_DEBUG) console.error(err.stack);
877
1182
  process.exit(1);
878
1183
  }
package/mcp/server.js CHANGED
@@ -63,6 +63,19 @@ const TOOLS = [
63
63
  description: 'List all available NAIDE compilation targets with details.',
64
64
  inputSchema: { type: 'object', properties: {} }
65
65
  },
66
+ {
67
+ name: 'naide_generate',
68
+ description: 'Generate NAIDE code from a natural language instruction. No AI — uses pattern matching and template composition with self-healing parser validation. Extremely lightweight, runs in microseconds.',
69
+ inputSchema: {
70
+ type: 'object',
71
+ properties: {
72
+ instruction: { type: 'string', description: 'Natural language instruction (e.g. "REST API for users with auth", "Discord bot", "todo app")' },
73
+ port: { type: 'number', description: 'Server port (default: 3000)' },
74
+ schemaName: { type: 'string', description: 'Override schema/entity name' }
75
+ },
76
+ required: ['instruction']
77
+ }
78
+ },
66
79
  {
67
80
  name: 'naide_spec',
68
81
  description: 'Get the NAIDE language specification. Use this to understand NAIDE syntax before writing code.',
@@ -133,6 +146,20 @@ async function handleToolCall(name, args) {
133
146
  return { content: [{ type: 'text', text: `NAIDE Compilation Targets (15):\n\n${'Target'.padEnd(12)} ${'Language'.padEnd(25)} ${'Server'.padEnd(20)} Flag\n${'─'.repeat(75)}\n${text}` }] };
134
147
  }
135
148
 
149
+ case 'naide_generate': {
150
+ try {
151
+ const { generate } = await import(resolve(__dirname, '..', 'src', 'gen.js'));
152
+ const opts = {};
153
+ if (args.port) opts.port = args.port;
154
+ if (args.schemaName) opts.schemaName = args.schemaName;
155
+ const result = generate(args.instruction, opts);
156
+ const meta = `[${result.intents.join(' + ')}]${result.schema ? ` → ${result.schema}` : ''} | valid: ${result.valid}${result.fixed ? ' (auto-fixed)' : ''}`;
157
+ return { content: [{ type: 'text', text: `${result.code}\n# ${meta}` }] };
158
+ } catch (e) {
159
+ return { content: [{ type: 'text', text: `Generation error: ${e.message}` }], isError: true };
160
+ }
161
+ }
162
+
136
163
  case 'naide_spec': {
137
164
  try {
138
165
  let spec = readFileSync(resolve(__dirname, '..', 'SPEC.naide'), 'utf-8');
@@ -165,7 +192,7 @@ async function handleMessage(msg) {
165
192
  respond(msg.id, {
166
193
  protocolVersion: '2024-11-05',
167
194
  capabilities: { tools: {} },
168
- serverInfo: { name: 'naide-mcp', version: '1.18.0' }
195
+ serverInfo: { name: 'naide-mcp', version: '1.21.0' }
169
196
  });
170
197
  break;
171
198
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naider",
3
- "version": "1.19.0",
3
+ "version": "1.21.0",
4
4
  "description": "NAIDE - Simpler than Python, compiles to 15 targets. AI-specialized language with 35+ built-in functions, syntax sugar (unless/until/repeat/swap/is/isnt), and 47 features. Targets: Node.js, Python, TypeScript, C, C++, Java, Go, Rust, PHP, Ruby, Kotlin, Swift, Dart, C#, Bun.",
5
5
  "main": "src/index.js",
6
6
  "exports": {