naider 1.24.5 → 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.
@@ -1,9 +1,19 @@
1
+ const EXPRESSION_TYPES = new Set([
2
+ 'Number', 'String', 'InterpolatedString', 'Bool', 'Null', 'Array', 'Object',
3
+ 'Identifier', 'Binary', 'Unary', 'Call', 'MemberAccess', 'Ternary', 'Await',
4
+ 'ArrowFunction', 'Spread', 'New', 'IndexAccess',
5
+ ]);
6
+
1
7
  export class TypeChecker {
2
8
  constructor() {
3
9
  this.scopes = [new Map()];
4
10
  this.errors = [];
5
11
  this.warnings = [];
12
+ this.errorKeys = new Set();
13
+ this.warningKeys = new Set();
14
+ this.visitedStatements = new WeakSet();
6
15
  this.functions = new Map();
16
+ this.returnTypes = [];
7
17
  }
8
18
 
9
19
  pushScope() { this.scopes.push(new Map()); }
@@ -21,18 +31,37 @@ export class TypeChecker {
21
31
  }
22
32
 
23
33
  error(msg, line) {
24
- this.errors.push({ message: msg, line: line || 0, severity: 'error' });
34
+ const diagnostic = { message: msg, line: line || 0, severity: 'error' };
35
+ const key = `${diagnostic.line}:${diagnostic.message}`;
36
+ if (this.errorKeys.has(key)) return;
37
+ this.errorKeys.add(key);
38
+ this.errors.push(diagnostic);
25
39
  }
26
40
 
27
41
  warn(msg, line) {
28
- this.warnings.push({ message: msg, line: line || 0, severity: 'warning' });
42
+ const diagnostic = { message: msg, line: line || 0, severity: 'warning' };
43
+ const key = `${diagnostic.line}:${diagnostic.message}`;
44
+ if (this.warningKeys.has(key)) return;
45
+ this.warningKeys.add(key);
46
+ this.warnings.push(diagnostic);
29
47
  }
30
48
 
31
49
  check(ast) {
50
+ for (const stmt of ast.body) {
51
+ if (stmt.type === 'Function') this.registerFunction(stmt);
52
+ }
32
53
  this.visitProgram(ast);
33
54
  return { errors: this.errors, warnings: this.warnings };
34
55
  }
35
56
 
57
+ registerFunction(node) {
58
+ this.functions.set(node.name, {
59
+ params: node.params.map(p => ({ name: p.name, type: p.type || 'any', hasDefault: p.defaultValue !== null, spread: p.spread })),
60
+ returnType: node.returnType || 'any',
61
+ isAsync: node.isAsync || false,
62
+ });
63
+ }
64
+
36
65
  visitProgram(node) {
37
66
  for (const stmt of node.body) {
38
67
  this.visitStatement(stmt);
@@ -40,7 +69,10 @@ export class TypeChecker {
40
69
  }
41
70
 
42
71
  visitStatement(node) {
72
+ if (this.visitedStatements.has(node)) return;
73
+ this.visitedStatements.add(node);
43
74
  const line = node._line || 0;
75
+ this.checkExpressions(node);
44
76
  switch (node.type) {
45
77
  case 'TypedVar': return this.visitTypedVar(node, line);
46
78
  case 'Function': return this.visitFunction(node, line);
@@ -51,11 +83,59 @@ export class TypeChecker {
51
83
  case 'For': return this.visitFor(node, line);
52
84
  case 'While': return this.visitWhile(node, line);
53
85
  case 'Try': return this.visitTry(node, line);
54
- case 'Server': return this.visitBlock(node.body, line);
55
- default: return;
86
+ case 'Server': return this.visitServer(node, line);
87
+ default: return this.visitNestedStatements(node);
56
88
  }
57
89
  }
58
90
 
91
+ checkExpressions(node) {
92
+ const seen = new WeakSet();
93
+ const visit = value => {
94
+ if (Array.isArray(value)) {
95
+ if (seen.has(value)) return;
96
+ seen.add(value);
97
+ for (const item of value) visit(item);
98
+ return;
99
+ }
100
+ if (!value || typeof value !== 'object') return;
101
+ if (seen.has(value)) return;
102
+ seen.add(value);
103
+
104
+ if (typeof value.type === 'string') {
105
+ if (!EXPRESSION_TYPES.has(value.type)) return;
106
+ this.inferType(value);
107
+ for (const [key, child] of Object.entries(value)) {
108
+ if (key !== 'type' && key !== '_line') visit(child);
109
+ }
110
+ return;
111
+ }
112
+
113
+ for (const child of Object.values(value)) visit(child);
114
+ };
115
+
116
+ for (const [key, value] of Object.entries(node)) {
117
+ if (key !== 'type' && key !== '_line') visit(value);
118
+ }
119
+ }
120
+
121
+ visitNestedStatements(value, seen = new WeakSet()) {
122
+ if (Array.isArray(value)) {
123
+ if (seen.has(value)) return;
124
+ seen.add(value);
125
+ for (const item of value) this.visitNestedStatements(item, seen);
126
+ return;
127
+ }
128
+ if (!value || typeof value !== 'object') return;
129
+ if (seen.has(value)) return;
130
+ seen.add(value);
131
+ if (typeof value.type === 'string') {
132
+ if (EXPRESSION_TYPES.has(value.type)) return;
133
+ this.visitStatement(value);
134
+ return;
135
+ }
136
+ for (const child of Object.values(value)) this.visitNestedStatements(child, seen);
137
+ }
138
+
59
139
  visitBlock(body, _line) {
60
140
  if (!body) return;
61
141
  this.pushScope();
@@ -80,26 +160,20 @@ export class TypeChecker {
80
160
  }
81
161
 
82
162
  visitFunction(node, line) {
83
- const paramTypes = {};
84
- for (const p of node.params) {
85
- paramTypes[p.name] = p.varType || 'any';
86
- }
87
-
88
- this.functions.set(node.name, {
89
- params: node.params.map(p => ({ name: p.name, type: p.varType || 'any' })),
90
- returnType: node.returnType || 'any',
91
- isAsync: node.isAsync || false,
92
- });
163
+ this.registerFunction(node);
93
164
 
94
165
  this.setType(node.name, 'function');
95
166
 
96
167
  this.pushScope();
97
168
  for (const p of node.params) {
98
- this.setType(p.name, p.varType || 'any');
169
+ this.setType(p.name, p.type || 'any');
170
+ if (p.defaultValue) this.inferType(p.defaultValue);
99
171
  }
172
+ this.returnTypes.push(node.returnType || 'any');
100
173
  for (const stmt of node.body) {
101
174
  this.visitStatement(stmt);
102
175
  }
176
+ this.returnTypes.pop();
103
177
  this.popScope();
104
178
  }
105
179
 
@@ -118,7 +192,22 @@ export class TypeChecker {
118
192
  }
119
193
  }
120
194
 
121
- visitReturn(node, line) {}
195
+ visitReturn(node, line) {
196
+ const expectedType = this.returnTypes[this.returnTypes.length - 1];
197
+ if (!expectedType || expectedType === 'any') return;
198
+
199
+ if (!node.value) {
200
+ if (expectedType !== 'void') {
201
+ this.error(`Return type mismatch: expected ${expectedType} but got void`, line);
202
+ }
203
+ return;
204
+ }
205
+
206
+ const actualType = this.inferType(node.value);
207
+ if (actualType !== 'any' && !this.typesCompatible(expectedType, actualType)) {
208
+ this.error(`Return type mismatch: expected ${expectedType} but got ${actualType}`, line);
209
+ }
210
+ }
122
211
 
123
212
  visitIf(node, line) {
124
213
  this.visitBlock(node.body, line);
@@ -168,6 +257,19 @@ export class TypeChecker {
168
257
  }
169
258
  }
170
259
 
260
+ visitServer(node, line) {
261
+ for (const route of node.routes || []) {
262
+ this.pushScope();
263
+ for (const param of route.params || []) {
264
+ this.setType(typeof param === 'string' ? param : param.name, 'any');
265
+ }
266
+ this.visitBlock(route.body, line);
267
+ this.popScope();
268
+ }
269
+ this.visitNestedStatements(node.middleware || []);
270
+ this.visitNestedStatements(node.body || []);
271
+ }
272
+
171
273
  inferType(node) {
172
274
  if (!node) return 'any';
173
275
  switch (node.type) {
@@ -177,7 +279,7 @@ export class TypeChecker {
177
279
  }
178
280
  case 'String': return 'str';
179
281
  case 'InterpolatedString': return 'str';
180
- case 'Boolean': return 'bool';
282
+ case 'Bool': return 'bool';
181
283
  case 'Null': return 'any';
182
284
  case 'Array': return 'list';
183
285
  case 'Object': return 'map';
@@ -220,7 +322,10 @@ export class TypeChecker {
220
322
  inferCallType(node) {
221
323
  if (node.callee.type === 'Identifier') {
222
324
  const fn = this.functions.get(node.callee.name);
223
- if (fn) return fn.returnType;
325
+ if (fn) {
326
+ this.checkCallArguments(node, fn);
327
+ return fn.returnType;
328
+ }
224
329
 
225
330
  const builtins = {
226
331
  'uuid': 'str', 'hash': 'str', 'verify': 'bool',
@@ -251,6 +356,30 @@ export class TypeChecker {
251
356
  return 'any';
252
357
  }
253
358
 
359
+ checkCallArguments(node, fn) {
360
+ const params = fn.params;
361
+ const line = node._line || 0;
362
+ const requiredCount = params.filter(p => !p.hasDefault && !p.spread).length;
363
+ const hasSpread = params.some(p => p.spread);
364
+
365
+ if (node.args.length < requiredCount || (!hasSpread && node.args.length > params.length)) {
366
+ const expected = hasSpread ? `at least ${requiredCount}` : `${requiredCount}${params.length === requiredCount ? '' : ` to ${params.length}`}`;
367
+ this.error(`Argument count mismatch for '${node.callee.name}': expected ${expected}, got ${node.args.length}`, line);
368
+ }
369
+
370
+ const spreadIndex = params.findIndex(param => param.spread);
371
+ for (let i = 0; i < node.args.length; i++) {
372
+ const paramIndex = spreadIndex >= 0 && i >= spreadIndex ? spreadIndex : i;
373
+ const param = params[paramIndex];
374
+ if (!param) continue;
375
+ const expectedType = param.type;
376
+ const actualType = this.inferType(node.args[i]);
377
+ if (expectedType !== 'any' && actualType !== 'any' && !this.typesCompatible(expectedType, actualType)) {
378
+ this.error(`Argument '${param.name}' of '${node.callee.name}' expects ${expectedType} but got ${actualType}`, line);
379
+ }
380
+ }
381
+ }
382
+
254
383
  typesCompatible(declared, actual) {
255
384
  if (declared === actual) return true;
256
385
  if (declared === 'any' || actual === 'any') return true;
@@ -1,22 +1,20 @@
1
1
  # NAIDE Language Support for VS Code
2
2
 
3
- Syntax highlighting and language support for **NAIDE** (`.naide`) and **NAIDE-X** (`.nx`) files.
3
+ Syntax highlighting and language support for **NAIDE** (`.naide`) files.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - Syntax highlighting for all NAIDE keywords, types, and operators
8
- - Syntax highlighting for NAIDE-X shorthand prefixes (`>`, `?`, `!`, `$`, `^`, `@`, etc.)
9
8
  - String interpolation highlighting (`"Hello {name}"`)
10
9
  - Auto-indentation for block structures
11
10
  - Bracket matching and auto-closing
12
- - Comment toggling (`#` for .naide, `--` for .nx)
11
+ - Comment toggling (`#`)
13
12
 
14
13
  ## File Associations
15
14
 
16
15
  | Extension | Language |
17
16
  |-----------|----------|
18
17
  | `.naide` | NAIDE |
19
- | `.nx` | NAIDE-X |
20
18
 
21
19
  ## Install
22
20
 
@@ -26,7 +24,7 @@ Syntax highlighting and language support for **NAIDE** (`.naide`) and **NAIDE-X*
26
24
  cd vscode-naide
27
25
  npm install -g @vscode/vsce
28
26
  vsce package
29
- code --install-extension naide-lang-1.0.0.vsix
27
+ code --install-extension naide-lang-2.0.1.vsix
30
28
  ```
31
29
 
32
30
  ### Manual
@@ -35,4 +33,4 @@ Copy `vscode-naide/` to `~/.vscode/extensions/naide-lang/` and restart VS Code.
35
33
 
36
34
  ## About NAIDE
37
35
 
38
- NAIDE is an AI-optimized programming language that transpiles to Node.js. See [github.com/irxk/naide](https://github.com/irxk/naide).
36
+ NAIDE is a programming language with one readable syntax, built-in diagnostics, and compiler targets. See [github.com/irxk/naide](https://github.com/irxk/naide).
@@ -18,10 +18,9 @@ function activate(context) {
18
18
  const clientOptions = {
19
19
  documentSelector: [
20
20
  { scheme: 'file', language: 'naide' },
21
- { scheme: 'file', language: 'naidex' },
22
21
  ],
23
22
  synchronize: {
24
- fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{naide,nx}'),
23
+ fileEvents: vscode.workspace.createFileSystemWatcher('**/*.naide'),
25
24
  },
26
25
  };
27
26
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "naide-lang",
3
- "version": "1.1.0",
3
+ "version": "2.0.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "naide-lang",
9
- "version": "1.1.0",
9
+ "version": "2.0.1",
10
10
  "dependencies": {
11
11
  "vscode-languageclient": "^9.0.0"
12
12
  },
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "naide-lang",
3
3
  "displayName": "NAIDE Language",
4
- "description": "Syntax highlighting, diagnostics, and autocomplete for NAIDE (.naide) and NAIDE-X (.nx)",
5
- "version": "1.1.0",
4
+ "description": "Syntax highlighting, diagnostics, and autocomplete for NAIDE (.naide)",
5
+ "version": "2.0.1",
6
6
  "publisher": "irxk",
7
7
  "engines": { "vscode": "^1.75.0" },
8
8
  "categories": ["Programming Languages"],
9
9
  "main": "./extension.js",
10
10
  "activationEvents": [
11
- "onLanguage:naide",
12
- "onLanguage:naidex"
11
+ "onLanguage:naide"
13
12
  ],
14
13
  "repository": {
15
14
  "type": "git",
@@ -22,12 +21,6 @@
22
21
  "aliases": ["NAIDE", "naide"],
23
22
  "extensions": [".naide"],
24
23
  "configuration": "./language-configuration-naide.json"
25
- },
26
- {
27
- "id": "naidex",
28
- "aliases": ["NAIDE-X", "naidex", "nx"],
29
- "extensions": [".nx"],
30
- "configuration": "./language-configuration-nx.json"
31
24
  }
32
25
  ],
33
26
  "grammars": [
@@ -35,11 +28,6 @@
35
28
  "language": "naide",
36
29
  "scopeName": "source.naide",
37
30
  "path": "./syntaxes/naide.tmLanguage.json"
38
- },
39
- {
40
- "language": "naidex",
41
- "scopeName": "source.naidex",
42
- "path": "./syntaxes/naidex.tmLanguage.json"
43
31
  }
44
32
  ],
45
33
  "configuration": {
package/SPEC-X.nx DELETED
@@ -1,276 +0,0 @@
1
- -- ============================================
2
- -- NAIDE-X Language Specification
3
- -- ~80% fewer tokens than JavaScript
4
- -- AI-only readability. Maximum generation speed.
5
- -- ============================================
6
- -- Rule: first char of line = intent
7
- -- > return ? if | elif : else
8
- -- @ loop * while ! try !! catch !!! ensure
9
- -- $ server ^ model < import % match X patch
10
- -- f func ~f async + export
11
- -- s:i:n:b:l:m:a: typed vars
12
- -- ~ await ~~ await.all
13
- -- ============================================
14
-
15
- -- Types: s=str i=int n=num b=bool l=list m=map a=any
16
- s:name="hello"
17
- i:count=42
18
- n:price=9.99
19
- b:active=true
20
- l:items=[1,2,3]
21
- m:cfg={host:"localhost",port:3000}
22
- a:data=null
23
-
24
- -- Mutable: ~ prefix
25
- ~i:counter=0
26
- ~s:label="init"
27
-
28
- -- String interpolation: "{expr}" (double quotes)
29
- s:greet="Hello {name}, count is {count}"
30
-
31
- -- Functions: f name(TYPE:param,...)RETTYPE
32
- f add(i:a,i:b)i
33
- >a+b
34
-
35
- f sayHi(s:who)
36
- log"Hi {who}"
37
-
38
- f greet2(s:name,s:prefix="Hello")
39
- log"{prefix}, {name}!"
40
-
41
- -- Async: ~f
42
- ~f fetchUser(s:id)m
43
- a:res=~fetch("/api/users/{id}")
44
- a:data=~res.json()
45
- >data
46
-
47
- -- Return: >
48
- -- Return with status: >.s CODE BODY
49
-
50
- -- If/elif/else: ? | :
51
- ?count>10
52
- log"many"
53
- |count>5
54
- log"some"
55
- :
56
- log"few"
57
-
58
- -- Inline ternary (same as NAIDE v1)
59
- -- s:size=if count>10 then "big" else "small"
60
-
61
- -- Each: @var<collection
62
- @item<items
63
- log item
64
-
65
- -- Each with key: @key,val<collection
66
- @k,v<cfg
67
- log"{k}: {v}"
68
-
69
- -- For range: @var<start..end
70
- @i<0..10
71
- log i
72
-
73
- -- While: *condition
74
- *active
75
- log"running"
76
- active=false
77
-
78
- -- Match: %value
79
- s:status="ok"
80
- %status
81
- "ok": log "success"
82
- "error": log "failed"
83
- _: log "unknown"
84
-
85
- -- Try/catch/ensure: ! / !!var / !!!
86
- ~f safe(s:url)m
87
- !
88
- a:data=~fetch(url)
89
- >{ok:true,data:data}
90
- !!e
91
- log.e"fail: {e.message}"
92
- >{ok:false,error:e.message}
93
- !!!
94
- log"request done"
95
-
96
- -- typeof / instanceof
97
- ?typeof x=="string"
98
- log"is string"
99
- ?err instanceof TypeError
100
- log"type error"
101
-
102
- -- Pipe: |> (same)
103
- l:result=[1,2,3,4,5]
104
- |>filter((x)=>x>2)
105
- |>map((x)=>x*10)
106
-
107
- -- Model: ^Name
108
- ^User
109
- s:name
110
- s:email
111
- i:age=0
112
- f greet()s
113
- >"Hi, I'm {self.name}"
114
- ~f save()
115
- log"Saving {self.name}..."
116
-
117
- -- Inheritance: ^Child<Parent
118
- ^Admin<User
119
- s:role="admin"
120
- f perms()l
121
- >["read","write","delete"]
122
-
123
- -- DB persistence: db "path/"
124
- db "data/"
125
-
126
- -- SQL database: db.sql "driver" "connection"
127
- -- db.sql "sqlite" "app.db"
128
- -- db.sql "postgres" "postgresql://localhost/mydb"
129
-
130
- -- Environment variables
131
- env:
132
- PORT int default(3000)
133
- JWT_SECRET str required
134
-
135
- -- Schema: types + modifiers
136
- schema User:
137
- id auto
138
- name str required min(2) max(50)
139
- email str required email unique
140
- role enum("admin","user") default("user")
141
- joined timestamp auto
142
-
143
- -- Server with high-level features
144
- $app:PORT
145
- cors "*"
146
- auth JWT_SECRET:
147
- protect "/api/*"
148
- public "/api/auth/*"
149
- limit "/api/*" 100 "1m"
150
- static "/public"
151
- crud "/api/users" User
152
- cookie
153
- session JWT_SECRET
154
- cache "/api/*" "5m"
155
- view "./views"
156
- sse "/events"
157
- upload "/api/upload" "avatar" (req,res):
158
- >{file:req.file.filename}
159
- -- Route middleware: [mid1, mid2]
160
- G"/admin"[authCheck](req,res)
161
- >{admin:true}
162
- P"/api/secure"[auth,logger](req,res)
163
- >req.body
164
- group "/api/v1":
165
- G"/status"
166
- >{version:"1.0"}
167
- G"/"
168
- >.h "<h1>Welcome</h1>"
169
- P"/api/auth/register"(req,res)
170
- s:hashed=hash(req.body.password)
171
- user=UserStore.create({...req.body,password:hashed})
172
- token=auth.sign({id:user.id})
173
- >{token,user}
174
- P"/api/auth/login"(req,res)
175
- user=UserStore.where({email:req.body.email})[0]
176
- ?not user
177
- >.s 401 {error:"Invalid credentials"}
178
- ?not verify(req.body.password,user.password)
179
- >.s 401 {error:"Invalid credentials"}
180
- token=sign({id:user.id})
181
- >{token}
182
- ws "/chat":
183
- on "connect":
184
- send({type:"welcome"})
185
- on "message" (data):
186
- broadcast(data)
187
-
188
- -- Error handler
189
- error (err, req, res):
190
- log.e err.message
191
- >.s 500 {error:"Internal error"}
192
-
193
- -- HTTP client (auto-imported)
194
- -- api.get(url) api.post(url,body) api.put(url,body) api.del(url) api.raw(url,opts)
195
-
196
- -- Return helpers
197
- -- >expr → JSON
198
- -- >.s CODE expr → status code
199
- -- >.r "/path" → redirect
200
- -- >.h "<html>" → HTML
201
- -- >.t "text" → plain text
202
- -- >.f "/file" → send file
203
- -- >.d "/file" → download
204
- -- >.v "tmpl" {} → render template
205
-
206
- -- Built-in functions (auto-imported)
207
- -- uuid() → UUID
208
- -- hash("password") → scrypt hash
209
- -- verify("pw",hashed) → verify
210
- -- sign({id:1}) → JWT (uses auth secret)
211
- -- sign({id:1},"secret") → JWT (explicit)
212
-
213
- -- Validate: auto-validate POST/PUT/PATCH bodies
214
- -- validate "/api/users" User
215
-
216
- -- Test (node:test)
217
- test "math":
218
- assert 1+1==2
219
- assert 2*3==6
220
-
221
- -- Queue (async job queue)
222
- queue jobs:
223
- job "notify" (data):
224
- log data.msg
225
-
226
- -- OpenAPI: auto-generate spec from schemas
227
- -- openapi "/docs"
228
-
229
- -- AI / LLM integration (auto-imported, zero-dep)
230
- -- s:answer=~ai.ask("Explain NAIDE")
231
- -- m:result=~ai.json("List 3 colors",{colors:["string"]})
232
- -- s:reply=~ai.chat(msgs)
233
- -- s:a=~ai.ask("hi",{model:"gpt-4o",maxTokens:100})
234
- -- Streaming: ~f main(): @chunk<~ai.stream("poem") ...
235
- -- Embed: l:vec=~ai.embed("hello")
236
- -- Similarity: n:score=ai.similarity(a,b)
237
-
238
- -- Prompt template
239
- -- prompt summarize {lang:"en"}:
240
- -- "Summarize in {lang}: {text}"
241
-
242
- -- Inter-file import (.naide/.nx → .mjs auto-rewrite)
243
- -- <{handler}"./routes.naide"
244
-
245
- -- Scheduled tasks
246
- every "5m":
247
- log"cleanup"
248
-
249
- -- Event watch
250
- watch User.create (event):
251
- log"new: {event.data.name}"
252
-
253
- -- Import: <module or <{names}"module"
254
- -- <express
255
- -- <{readFile,writeFile}"fs/promises"
256
-
257
- -- Export: + prefix
258
- +f helper()s
259
- >"exported"
260
- +s:VER="1.0.0"
261
-
262
- -- Log: log, log.e, log.w, log.i, log.d
263
- log"info"
264
- log.e"error"
265
- log.w"warning"
266
- log.i"info level"
267
- log.d"debug level"
268
-
269
- -- Null safe: ?. and ?? (same)
270
- a:val=data?.nested?.value??"default"
271
-
272
- -- Await all: ~~[expr1,expr2]
273
-
274
- -- Spread: ...
275
- l:combined=[...items,4,5,6]
276
- m:merged={...cfg,debug:true}
package/assets/nx.ico DELETED
Binary file
Binary file
@@ -1,21 +0,0 @@
1
- -- AI-powered API (NAIDE-X)
2
- -- Set AI_KEY or OPENAI_API_KEY env var
3
-
4
- $app:3000
5
- cors "*"
6
-
7
- P"/api/ask"(req,res)
8
- s:answer=~ai.ask(req.body.prompt)
9
- >{answer}
10
-
11
- P"/api/summarize"(req,res)
12
- s:summary=~ai.ask("Summarize: {req.body.text}")
13
- >{summary}
14
-
15
- P"/api/extract"(req,res)
16
- m:data=~ai.json("Extract name, email, phone: {req.body.text}",{name:"string",email:"string",phone:"string"})
17
- >data
18
-
19
- P"/api/chat"(req,res)
20
- s:reply=~ai.chat(req.body.messages)
21
- >{reply}