future-lang 0.4.0 → 0.4.2

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/ARCHITECTURE.md CHANGED
@@ -15,22 +15,25 @@ future-lang/
15
15
  │ ├── index.js # Public API — compile(source, options)
16
16
  │ ├── lexer.js # Phase 1: source text → token list
17
17
  │ ├── parser.js # Phase 2: token list → AST
18
- │ ├── ast.js # AST node types and factory functions (23 types)
18
+ │ ├── ast.js # AST node types and factory functions (24 types)
19
19
  │ ├── generator.js # Phase 3: AST → JavaScript source
20
20
  │ ├── errors.js # FutureError with line/column tracking
21
- └── cli.js # CLI binary: future run / future compile
21
+ ├── formatter.js # Line-based auto-formatter (future fmt)
22
+ │ ├── sourcemap.js # VLQ encoder + Source Map v3 builder
23
+ │ └── cli.js # CLI binary: 9 commands including future test
22
24
 
23
25
  ├── runtime/ # Capability modules (imported by generated JS)
24
26
  │ ├── index.js # Aggregator: runtime object + manifest + introspection
25
27
  │ │
26
- │ ├── ai.js # Text generation — pluggable provider architecture
27
- │ ├── http.js # REST API consumption (fetch-based)
28
+ │ ├── ai.js # Text generation — ask/chat/stream accept opts {temperature, max_tokens, model}
29
+ │ ├── http.js # REST API HttpError class, configure() for global headers/timeout
28
30
  │ ├── mqtt.js # Pub/sub messaging (real broker or in-process loopback)
29
31
  │ ├── tts.js # Text-to-speech (system engine)
30
32
  │ ├── rag.js # RAG — chunk → embed → store → retrieve → answer
31
33
  │ ├── vision.js # Vision AI — describe, detect, ocr, classify, compare
32
34
  │ ├── home.js # Home automation (composes over MQTT)
33
35
  │ │
36
+ │ ├── assert.js # Test assertions — ok/equal/notEqual/deepEqual/fail
34
37
  │ ├── memory.js # In-process key-value store (set/get/search/delete/forget)
35
38
  │ ├── schedule.js # Recurring / one-shot / cron scheduling
36
39
  │ ├── system.js # OS utilities: exec, open, notify, read, write
@@ -41,7 +44,7 @@ future-lang/
41
44
  │ │
42
45
  │ ├── providers/ # AI provider implementations
43
46
  │ │ ├── index.js # Provider factory + env-var resolution
44
- │ │ ├── anthropic.js # Anthropic Messages API (native format)
47
+ │ │ ├── anthropic.js # Anthropic Messages API AiError class, opts forwarding
45
48
  │ │ ├── openai-compat.js # OpenAI-compatible (OpenAI, Ollama, Gemini, OpenRouter, …)
46
49
  │ │ └── util.js # SSE parser, keyword vector, cosine similarity
47
50
  │ │
@@ -69,6 +72,7 @@ future-lang/
69
72
 
70
73
  ├── future-browser.js # Browser entry point: window.Future + <script type="future">
71
74
  ├── future-playground.html # In-browser editor (11 examples, live compile)
75
+ ├── FUTURE_FOR_LLMS.md # BNF grammar + all APIs — quick-reference for AI assistants
72
76
  ├── package.json
73
77
  ├── ARCHITECTURE.md # This file
74
78
  ├── ROADMAP.md # Feature roadmap
@@ -114,7 +118,7 @@ In **browser mode** (`browserMode: true` option), the `import` statement is omit
114
118
 
115
119
  ## Lexer
116
120
 
117
- ### Keywords (24)
121
+ ### Keywords (26)
118
122
 
119
123
  | Keyword | Token | Purpose |
120
124
  |---------|-------|---------|
@@ -136,7 +140,8 @@ In **browser mode** (`browserMode: true` option), the `import` statement is omit
136
140
  | `null` / `none` | NULL | Null literal (two spellings) |
137
141
  | `stream` | STREAM | Streaming statement |
138
142
  | `agent` | AGENT | Agent declaration |
139
- | `use` | USE | Capability declaration inside `agent` |
143
+ | `use` | USE | Import statement / capability declaration inside `agent` |
144
+ | `as` | AS | Alias in `use "..." as alias` |
140
145
 
141
146
  ### String escape
142
147
 
@@ -144,12 +149,13 @@ In **browser mode** (`browserMode: true` option), the `import` statement is omit
144
149
 
145
150
  ---
146
151
 
147
- ## AST Node Types (23)
152
+ ## AST Node Types (24)
148
153
 
149
154
  | Category | Nodes |
150
155
  |----------|-------|
151
156
  | Program | `Program` |
152
157
  | Statements | `PrintStatement`, `Assignment`, `IfStatement`, `FunctionDeclaration`, `ReturnStatement`, `ExpressionStatement` |
158
+ | Import | `UseStatement` — `use "path"` / `use "path" as alias` |
153
159
  | Control flow | `ForStatement`, `WhileStatement`, `TryStatement` |
154
160
  | Event statements | `OnStatement`, `EveryStatement` |
155
161
  | AI/IoT statements | `AgentDeclaration`, `StreamStatement` |
@@ -191,12 +197,37 @@ export const NAMESPACES = new Set([
191
197
  'ai', 'http', 'mqtt', 'tts',
192
198
  'rag', 'vision', 'home',
193
199
  'memory', 'schedule', 'system', 'device',
194
- 'math',
200
+ 'math', 'assert',
195
201
  ]);
196
202
  ```
197
203
 
198
204
  Any identifier in this set, when used as the object of a `MemberExpression` or `CallExpression`, is routed through `__rt` in ASYNC mode. Adding a new capability is just a name in this set plus a matching runtime module — no grammar change.
199
205
 
206
+ `use ... as alias` imports are tracked in a `useAliases` Set and explicitly excluded from namespace routing — `m.add()` never becomes `__rt.m.add()`.
207
+
208
+ ### Source maps (`sourceMaps` option)
209
+
210
+ When `compile(source, { sourceMaps: true })` is used, the generator prefixes each top-level statement line with `/*@FL:N*/` (where N is the original `.future` line number). `src/sourcemap.js` post-processes this output:
211
+
212
+ 1. Scans the generated JS line by line.
213
+ 2. Strips `/*@FL:N*/` markers.
214
+ 3. Builds VLQ-encoded `mappings` in Source Map v3 format.
215
+ 4. Returns `{ code: cleanJS, map: { version: 3, sources, sourcesContent, mappings } }`.
216
+
217
+ The CLI appends `//# sourceMappingURL=file.js.map` to the clean JS and writes the map as JSON.
218
+
219
+ ### Import system (UseStatement)
220
+
221
+ `use "./file.future"` statements are emitted before all other code. At compile time, when `resolveSource` is provided, the compiler reads the imported file, parses it, and extracts top-level `FunctionDeclaration` names. This enables named imports:
222
+
223
+ ```js
224
+ import { formatName, greet } from "./utils.js"; // named import (default)
225
+ import * as m from "./math.js"; // namespace import (alias)
226
+ import * as df from "date-fns"; // npm package (alias)
227
+ ```
228
+
229
+ The `pathMap` option (a `Map<futurePath, fileURL>`) allows `future run` to redirect imports to temp `.mjs` files compiled in `tmpdir`.
230
+
200
231
  ### String interpolation
201
232
 
202
233
  String literals containing `{identifier}` or `{identifier.prop}` are emitted as JS template literals. Namespace references inside strings are correctly prefixed with `__rt.` in ASYNC mode:
@@ -227,7 +258,7 @@ In ASYNC mode, ALL call expressions where the callee is a `MemberExpression` are
227
258
  ```
228
259
  runtime/index.js
229
260
 
230
- ├── Imports 12 capability modules (+ readline for input())
261
+ ├── Imports 13 capability modules (+ readline for input())
231
262
  ├── Exports `runtime` object → used as `__rt` in generated JS
232
263
  ├── Exports `manifest` → structured metadata for every function
233
264
  └── Attaches introspection:
@@ -237,6 +268,8 @@ runtime/index.js
237
268
  runtime.input(prompt) → Promise<string> (stdin)
238
269
  ```
239
270
 
271
+ When `FUTURE_DEBUG=1` (`future run --debug`), the runtime is wrapped by `wrapDebug()` which proxies every namespace method to log timing and arguments to stderr with ANSI colours.
272
+
240
273
  ### Manifest shape (per function)
241
274
 
242
275
  ```js
@@ -402,14 +435,15 @@ await __rt.ai.stream("Tell me a story", async (chunk) => {
402
435
 
403
436
  ---
404
437
 
405
- ## Adding a New Capability (4 steps)
438
+ ## Adding a New Capability (5 steps)
406
439
 
407
440
  1. Create `runtime/mymodule.js` with named exports.
408
441
  2. Import it in `runtime/index.js`, add to `runtime` object, `MODULE_NAMES`, and `manifest`.
409
442
  3. Add the namespace name to `NAMESPACES` in `src/generator.js`.
410
- 4. Add the module to `browserRuntime` in `runtime/browser.js` if browser support is wanted.
443
+ 4. Add the namespace name to `RESERVED_NAMESPACES` in `src/parser.js`.
444
+ 5. Add the module to `browserRuntime` in `runtime/browser.js` if browser support is wanted.
411
445
 
412
- No grammar, lexer, parser, or AST changes needed.
446
+ No grammar, lexer, or AST changes needed.
413
447
 
414
448
  ---
415
449
 
@@ -4,6 +4,19 @@ Future is a small language that compiles to JavaScript. It does NOT exist in you
4
4
 
5
5
  ---
6
6
 
7
+ ## Capability layers
8
+
9
+ | Layer | Namespaces | Notes |
10
+ |-------|-----------|-------|
11
+ | **Core language** | *(none)* | variables, if/end, for/end, while/end, try/catch/end, functions, lists, objects, strings |
12
+ | **Standard** | `math` `http` `memory` `system` `schedule` | General-purpose I/O; triggers async mode |
13
+ | **Extended** | `ai` `rag` `vision` `mqtt` `tts` `home` `device` `agent` | AI, IoT, automation; triggers async mode |
14
+ | **Testing** | `assert` | Use only in `*.test.future` files |
15
+
16
+ Any call from Standard or Extended triggers ASYNC mode automatically.
17
+
18
+ ---
19
+
7
20
  ## Reserved words
8
21
 
9
22
  ```
@@ -14,7 +27,7 @@ agent use as
14
27
 
15
28
  Reserved namespaces (cannot be reassigned or used as function names):
16
29
  ```
17
- ai http mqtt tts rag vision home memory schedule system device math
30
+ ai http mqtt tts rag vision home memory schedule system device math assert
18
31
  ```
19
32
 
20
33
  ---
@@ -176,6 +189,17 @@ embed = ai.embed("text to embed")
176
189
  ai.configure("openai", "sk-...")
177
190
  ai.configure("ollama")
178
191
 
192
+ # With inference options
193
+ answer = ai.ask("Explain quantum physics", { temperature: 0.2 max_tokens: 200 })
194
+ reply = ai.chat(messages, { model: "gpt-4o" temperature: 0.7 })
195
+
196
+ # Structured response: text + token counts + model + provider
197
+ result = ai.complete("Summarise this in one line.")
198
+ print result.text
199
+ print result.tokens.total # total tokens used
200
+ print result.model # e.g. "claude-sonnet-4-6"
201
+ print result.provider # e.g. "anthropic"
202
+
179
203
  stream ai.ask("Tell me a story")
180
204
  print chunk
181
205
  end
@@ -224,7 +248,36 @@ end
224
248
  # schedule.once and schedule.cron also available
225
249
  ```
226
250
 
227
- ### `http`, `system`, `rag`, `vision`, `home`, `device`
251
+ ### `http`
252
+ ```
253
+ data = http.get("https://api.example.com/todos/1")
254
+ print data.title
255
+
256
+ res = http.post("https://api.example.com/items", { name: "Widget" price: 9.99 })
257
+ print res.id
258
+
259
+ # Global config (call once at the top of your program)
260
+ http.configure({ headers: { Authorization: "Bearer {token}" } timeout: 5000 })
261
+
262
+ # Errors have .status, .code, .url, .body properties
263
+ try
264
+ data = http.get("https://api.example.com/private")
265
+ catch err
266
+ print "Status: {err.status}"
267
+ print "Code: {err.code}"
268
+ end
269
+ ```
270
+
271
+ ### `assert` (use in *.test.future files)
272
+ ```
273
+ assert.ok(value)
274
+ assert.equal(actual, expected)
275
+ assert.notEqual(a, b)
276
+ assert.deepEqual(obj1, obj2)
277
+ assert.fail("custom message")
278
+ ```
279
+
280
+ ### `system`, `rag`, `vision`, `home`, `device`
228
281
  See [README.md](README.md) for full API tables.
229
282
 
230
283
  ### `math`
package/MIGRATION.md CHANGED
@@ -4,7 +4,215 @@ All releases are **additive only**. No existing Future program has ever required
4
4
 
5
5
  ---
6
6
 
7
- ## v0.3.1 → v0.3.2 (current — Phase 7: General-Purpose Programming)
7
+ ## v0.4.0 → v0.4.1 (current — Gemini improvements)
8
+
9
+ **No breaking changes.**
10
+
11
+ ### AI inference options
12
+
13
+ `ai.ask`, `ai.chat`, and `ai.stream` now accept an optional second argument with inference parameters:
14
+
15
+ ```future
16
+ # temperature controls creativity (0.0 = deterministic, 1.0 = creative)
17
+ precise = ai.ask("List the planets.", { temperature: 0.1 max_tokens: 100 })
18
+ creative = ai.chat(messages, { temperature: 0.9 model: "gpt-4o" })
19
+ ai.stream(prompt, { temperature: 0.7 })
20
+ ```
21
+
22
+ Supported fields: `temperature`, `max_tokens`, `model`, `system` (Anthropic only).
23
+ Both providers (Anthropic native, OpenAI-compat) forward all opts to the API.
24
+
25
+ ### Structured errors
26
+
27
+ `HttpError` and `AiError` replace generic `Error` objects. Catchable with `try/catch err`:
28
+
29
+ ```future
30
+ try
31
+ data = http.get("https://api.example.com/private")
32
+ catch err
33
+ print "{err.status}" # 401
34
+ print "{err.code}" # HTTP_401
35
+ print "{err.url}" # https://api.example.com/private
36
+ end
37
+
38
+ try
39
+ reply = ai.ask("hello")
40
+ catch err
41
+ print "{err.provider}" # anthropic
42
+ print "{err.status}" # 429
43
+ print "{err.code}" # AI_HTTP_429
44
+ end
45
+ ```
46
+
47
+ Error classes are exported from `runtime/providers/anthropic.js` (`AiError`) and `runtime/http.js` (`HttpError`) for use in JS integrations.
48
+
49
+ ### `http.configure()` — global request defaults
50
+
51
+ ```future
52
+ # Call once at the top of your program
53
+ http.configure({ headers: { Authorization: "Bearer {token}" } timeout: 5000 })
54
+
55
+ # All subsequent http.get / http.post calls include the header and timeout automatically
56
+ data = http.get("https://api.example.com/me")
57
+ ```
58
+
59
+ Supported fields: `headers` (merged with per-call headers), `timeout` (ms, uses `AbortSignal.timeout`).
60
+
61
+ ### Source maps (`future compile --sourcemap`)
62
+
63
+ ```bash
64
+ future compile --sourcemap program.future
65
+ # Produces: program.js + program.js.map
66
+ ```
67
+
68
+ The `.js.map` is a standard Source Map v3 file. Stack traces in Node.js, VS Code, and browser DevTools automatically map back to the original `.future` line numbers.
69
+
70
+ The generator embeds `/*@FL:N*/` markers at each statement and `src/sourcemap.js` post-processes them into VLQ-encoded mappings.
71
+
72
+ ### `future test` command + `assert` namespace
73
+
74
+ ```bash
75
+ future test # finds and runs all *.test.future / test/**/*.future files
76
+ future test myfeature # filter by filename substring
77
+ ```
78
+
79
+ Test files use the reserved `assert` namespace:
80
+
81
+ ```future
82
+ # calculator.test.future
83
+ assert.equal(1 + 1, 2)
84
+ assert.ok(math.sqrt(16) == 4)
85
+ assert.notEqual("hello", "world")
86
+ assert.deepEqual([1, 2, 3], [1, 2, 3])
87
+ ```
88
+
89
+ Exit code 0 when all pass, 1 when any fail. `assert.*` calls throw `AssertionError` on failure — the test runner catches them and reports per-file results.
90
+
91
+ `assert` is a reserved namespace — it cannot be redefined by user code.
92
+
93
+ ### Internal changes
94
+
95
+ - `runtime/assert.js` — new module, wraps `node:assert/strict`
96
+ - `src/sourcemap.js` — new module, VLQ encoder + Source Map v3 builder
97
+ - `runtime/providers/anthropic.js` — exports `AiError` class; `chat`/`stream` accept `opts`
98
+ - `runtime/providers/openai-compat.js` — imports `AiError`; `chat`/`stream` accept `opts`
99
+ - `runtime/http.js` — exports `HttpError` class; `get`/`post` throw it; adds `configure()`; uses `AbortSignal.timeout`
100
+ - `runtime/index.js` — `assert` added to module list, `_base`, and `manifest`
101
+ - `src/generator.js` — `assert` added to `NAMESPACES`; `sourceMaps` option emits `/*@FL:N*/` markers
102
+ - `src/parser.js` — `assert` added to `RESERVED_NAMESPACES`
103
+ - `src/cli.js` — `future test` command; `--sourcemap` flag in `future compile`; calls `buildSourceMap()` to strip markers and write `.js.map`
104
+
105
+ ---
106
+
107
+ ## v0.3.2 → v0.4.0 (CLI + Import system + Language improvements)
108
+
109
+ **No breaking changes.**
110
+
111
+ ### CLI commands
112
+
113
+ ```bash
114
+ future run <file.future> # compile + run
115
+ future compile <file.future> # compile to .js next to source
116
+ future new <name> # scaffold a new project directory
117
+ future check <file.future> # syntax-check only, no output
118
+ future fmt <file.future> # auto-format source in-place
119
+ future playground # launch the interactive playground
120
+ future doctor # check Node.js version, runtime, AI env, MQTT, etc.
121
+ future --version # show version
122
+ future run --debug <file> # print per-call timing to stderr (FUTURE_DEBUG=1)
123
+ ```
124
+
125
+ ### Import system (`use`)
126
+
127
+ ```future
128
+ # Import all top-level functions by name
129
+ use "./utils.future"
130
+ print formatName("Alice")
131
+
132
+ # Import as a namespace
133
+ use "./math.future" as m
134
+ result = m.add(10, 20)
135
+
136
+ # Import an npm package as a namespace
137
+ use "date-fns" as df
138
+ ```
139
+
140
+ Compiles to standard ES module imports:
141
+
142
+ ```js
143
+ import { formatName } from "./utils.js";
144
+ import * as m from "./math.js";
145
+ import * as df from "date-fns";
146
+ ```
147
+
148
+ The compiler reads imported `.future` files at compile time, parses them, and extracts top-level function names to generate named imports instead of wildcard imports. Dependencies are compiled recursively.
149
+
150
+ `use ... as alias` aliases are excluded from `__rt` routing — `m.add()` does not become `__rt.m.add()`.
151
+
152
+ ### `else if` chains
153
+
154
+ ```future
155
+ if score >= 90
156
+ print "A"
157
+ else if score >= 80
158
+ print "B"
159
+ else if score >= 70
160
+ print "C"
161
+ else
162
+ print "F"
163
+ end
164
+ ```
165
+
166
+ One `end` closes the entire chain. Previously required nesting.
167
+
168
+ ### Reserved namespace protection
169
+
170
+ Trying to reassign a namespace name now raises a compile-time error:
171
+
172
+ ```future
173
+ math = 42 # error[parse]: 'math' is a reserved namespace
174
+ http = {} # error[parse]: 'http' is a reserved namespace
175
+ ```
176
+
177
+ ### Async handler error safety (`__safe`)
178
+
179
+ Programs that use `on`, `every`, or `stream` now wrap their handlers in `__safe`. Errors inside handlers are logged to `stderr` with `[future:ns]` prefix instead of crashing the process silently:
180
+
181
+ ```js
182
+ const __safe = (ns, fn) => async (...a) => {
183
+ try { return await fn(...a); }
184
+ catch (e) { console.error(`[future:${ns}]`, e.message); }
185
+ };
186
+ ```
187
+
188
+ ### Better error messages
189
+
190
+ Parse errors now show the source line and a `^` pointer:
191
+
192
+ ```
193
+ error[parse]: Expected 'end' to close 'if' — did you forget 'end'?
194
+ --> hello.future:5:1
195
+ 5 | x = 1
196
+ ^
197
+ ```
198
+
199
+ ### `FUTURE_FOR_LLMS.md`
200
+
201
+ A complete quick-reference for AI assistants generating Future code: BNF grammar, all keywords, all namespace APIs, every construct with an example, common mistakes, and what-compiles-to-what pairs.
202
+
203
+ ### Internal changes
204
+
205
+ - `src/lexer.js` — `as` keyword added (`AS` token)
206
+ - `src/ast.js` — `UseStatement` node type and factory added
207
+ - `src/parser.js` — `parseUse()`, `parseIf(isChained)` updated; `RESERVED_NAMESPACES` set added
208
+ - `src/generator.js` — `genUseStatement()`, `useAliases` Set, `isModule` and `pathMap` options, `__safe` emission, `else if` chain detection
209
+ - `src/index.js` — `compile()` accepts `resolveSource`, `isModule`, `pathMap`, `importedNames` options
210
+ - `src/formatter.js` — new module: line-based indentation formatter
211
+ - `src/cli.js` — full rewrite; `compileDepsToTemp()` for `future run`; all CLI commands implemented
212
+
213
+ ---
214
+
215
+ ## v0.3.1 → v0.3.2 (Phase 7: General-Purpose Programming)
8
216
 
9
217
  **No breaking changes.**
10
218
 
package/README.md CHANGED
@@ -164,6 +164,18 @@ In the browser this uses `window.prompt()`. In a Node.js CLI program it reads fr
164
164
 
165
165
  Future programs talk to the outside world through **namespace calls**. The compiler detects them and automatically switches the program to async mode — you never write `async` or `await`.
166
166
 
167
+ ### Capability layers
168
+
169
+ Future organises its built-ins into three layers. You only need to know the layer you're using.
170
+
171
+ | Layer | What it includes | Typical use |
172
+ |-------|-----------------|-------------|
173
+ | **Core language** | variables, functions, `if/else/end`, `for`, `while`, `try/catch`, lists, objects, string interpolation | Any program — no external calls |
174
+ | **Standard capabilities** | `math`, `http`, `memory`, `system`, `schedule` | General-purpose programs with I/O |
175
+ | **Extended modules** | `ai`, `rag`, `vision`, `mqtt`, `tts`, `home`, `device`, `agent`, `assert` | AI, IoT, and automation programs |
176
+
177
+ Any call from Standard or Extended triggers async mode — the compiler handles it automatically.
178
+
167
179
  ```future
168
180
  # HTTP
169
181
  todo = http.get("https://jsonplaceholder.typicode.com/todos/1")
@@ -182,8 +194,8 @@ mqtt.publish("home/livingroom/light", "on")
182
194
 
183
195
  | Namespace | Functions | Notes |
184
196
  |------------|-----------|-------|
185
- | `http` | `get(url)`, `post(url, body)` | Parses JSON automatically |
186
- | `ai` | `ask(prompt)`, `chat(messages)`, `embed(text)`, `stream(prompt, cb)`, `configure(provider, key)` | Pluggable providers |
197
+ | `http` | `get(url)`, `post(url, body)`, `configure(opts)` | Parses JSON automatically; throws `HttpError` with `.status`, `.code`, `.body` |
198
+ | `ai` | `ask(prompt, opts?)`, `chat(messages, opts?)`, `embed(text)`, `stream(prompt, cb, opts?)`, `configure(provider, key)` | opts: `{ temperature, max_tokens, model }`; throws `AiError` |
187
199
  | `tts` | `speak(text)` | System engine (`say` / SAPI / `espeak-ng`) |
188
200
  | `mqtt` | `publish(topic, msg)`, `subscribe(topic, handler)` | Real broker or in-process loopback |
189
201
  | `memory` | `set(key, v)`, `get(key)`, `delete(key)`, `search(q)`, `forget(pattern?)` | In-process key-value store |
@@ -194,6 +206,7 @@ mqtt.publish("home/livingroom/light", "on")
194
206
  | `home` | `turnOn(device)`, `turnOff(device)`, `set(device, value)` | Home automation via MQTT |
195
207
  | `math` | `round`, `floor`, `ceil`, `abs`, `sqrt`, `pow`, `log`, `random`, `min`, `max`, `pi`, `e` | Full Math wrapper |
196
208
  | `device` | `register(config)`, `get(name)`, `list()` | IoT device registry |
209
+ | `assert` | `ok(val)`, `equal(a, b)`, `notEqual(a, b)`, `deepEqual(a, b)`, `fail(msg?)` | Use in `*.test.future` files |
197
210
 
198
211
  ### Configuration (environment variables)
199
212
 
@@ -211,12 +224,56 @@ FUTURE_VECTOR_DB=memory # memory | file | qdrant
211
224
  ## AI configuration
212
225
 
213
226
  ```future
214
- # From code
227
+ # Provider selection
215
228
  ai.configure("openai", "sk-...")
216
229
  ai.configure("ollama") # local, no key needed
217
230
 
231
+ # Basic usage
218
232
  answer = ai.ask("What is 2 + 2?")
219
233
  print answer
234
+
235
+ # With inference options
236
+ precise = ai.ask("List the planets.", { temperature: 0.1 max_tokens: 150 })
237
+ creative = ai.chat(messages, { temperature: 0.9 model: "gpt-4o" })
238
+
239
+ # Structured response — text + token counts + model + provider
240
+ result = ai.complete("Explain recursion in one sentence.")
241
+ print result.text
242
+ print "Tokens used: {result.tokens.total}"
243
+ print "Model: {result.model}"
244
+ print "Provider: {result.provider}"
245
+ ```
246
+
247
+ `ai.ask()` returns a plain string. `ai.complete()` returns `{ text, model, provider, tokens: { input, output, total } }` — useful when you need to track costs or log which model answered.
248
+
249
+ ## HTTP configuration
250
+
251
+ ```future
252
+ # Set global headers and timeout once at the top of your program
253
+ http.configure({ headers: { Authorization: "Bearer {token}" } timeout: 5000 })
254
+
255
+ data = http.get("https://api.example.com/me") # Authorization header included automatically
256
+ ```
257
+
258
+ ## Structured errors
259
+
260
+ HTTP and AI errors now carry structured data you can inspect:
261
+
262
+ ```future
263
+ try
264
+ data = http.get("https://api.example.com/private")
265
+ catch err
266
+ print "Status: {err.status}" # e.g. 401
267
+ print "Code: {err.code}" # e.g. HTTP_401
268
+ print "URL: {err.url}"
269
+ end
270
+
271
+ try
272
+ reply = ai.ask("hello")
273
+ catch err
274
+ print "Provider: {err.provider}" # e.g. anthropic
275
+ print "Status: {err.status}" # e.g. 429
276
+ end
220
277
  ```
221
278
 
222
279
  ---
@@ -333,14 +390,49 @@ Open `future-playground.html` in any browser for a live editor with 11 built-in
333
390
  ```bash
334
391
  npm install -g future-lang
335
392
 
336
- future --version # show version
337
- future new myapp # create a new project
338
- future run program.future # compile + run
339
- future compile program.future # compile to JavaScript
340
- future check program.future # syntax check only
341
- future fmt program.future # format source in-place
342
- future playground # launch the interactive playground
343
- future doctor # check your environment
393
+ future --version # show version
394
+ future new myapp # create a new project
395
+ future run program.future # compile + run
396
+ future run --debug program.future # run with per-call timing logs
397
+ future compile program.future # compile to JavaScript
398
+ future compile --sourcemap program.future # compile + emit .js.map
399
+ future test # run all *.test.future files
400
+ future test myfeature # run matching test files
401
+ future ast program.future # print the AST as JSON
402
+ future ast --pretty program.future # indented JSON
403
+ future check program.future # syntax check only
404
+ future fmt program.future # format source in-place
405
+ future playground # launch the interactive playground
406
+ future doctor # check your environment
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Testing
412
+
413
+ Name your test files `*.test.future` (or put them in a `test/` folder) and use the `assert` namespace:
414
+
415
+ ```future
416
+ # math.test.future
417
+
418
+ assert.equal(math.round(3.7), 4)
419
+ assert.equal(math.sqrt(16), 4)
420
+ assert.ok(math.pi > 3.14)
421
+ assert.notEqual(math.random(), math.random())
422
+ print "math tests passed"
423
+ ```
424
+
425
+ ```bash
426
+ future test # runs all *.test.future files
427
+ future test math # runs files matching "math"
428
+ ```
429
+
430
+ Output:
431
+ ```
432
+ math tests passed
433
+ ✓ math.test.future
434
+
435
+ 1/1 tests passed
344
436
  ```
345
437
 
346
438
  ---