jac-coder 0.1.0__py3-none-any.whl
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.
- jac_coder/__init__.jac +0 -0
- jac_coder/api.jac +82 -0
- jac_coder/cli_entry.py +25 -0
- jac_coder/config.jac +36 -0
- jac_coder/context.jac +17 -0
- jac_coder/data/examples/ai_agent.md +90 -0
- jac_coder/data/examples/blog_app.md +386 -0
- jac_coder/data/examples/core_patterns.md +321 -0
- jac_coder/data/examples/todo_app.md +321 -0
- jac_coder/data/reference/ai.md +131 -0
- jac_coder/data/reference/backend.md +215 -0
- jac_coder/data/reference/frontend.md +271 -0
- jac_coder/data/reference/osp.md +229 -0
- jac_coder/data/reference/pitfalls.md +141 -0
- jac_coder/data/reference/syntax.md +159 -0
- jac_coder/data/rules/core_jac.md +559 -0
- jac_coder/data/rules/fullstack.md +362 -0
- jac_coder/data/rules/workflow.md +88 -0
- jac_coder/events.jac +110 -0
- jac_coder/impl/api.impl.jac +399 -0
- jac_coder/impl/config.impl.jac +163 -0
- jac_coder/impl/context.impl.jac +117 -0
- jac_coder/impl/mcp_manager.impl.jac +380 -0
- jac_coder/impl/memory.impl.jac +247 -0
- jac_coder/impl/nodes.impl.jac +259 -0
- jac_coder/impl/permission.impl.jac +62 -0
- jac_coder/impl/walkers.impl.jac +298 -0
- jac_coder/mcp_manager.jac +35 -0
- jac_coder/memory.jac +15 -0
- jac_coder/nodes.jac +306 -0
- jac_coder/permission.jac +19 -0
- jac_coder/serve_entry.jac +30 -0
- jac_coder/server.jac +324 -0
- jac_coder/tool/__init__.jac +17 -0
- jac_coder/tool/checked.jac +10 -0
- jac_coder/tool/delegation.jac +23 -0
- jac_coder/tool/filesystem.jac +25 -0
- jac_coder/tool/git.jac +18 -0
- jac_coder/tool/guarded.jac +23 -0
- jac_coder/tool/impl/checked.impl.jac +38 -0
- jac_coder/tool/impl/delegation.impl.jac +157 -0
- jac_coder/tool/impl/filesystem.impl.jac +781 -0
- jac_coder/tool/impl/git.impl.jac +115 -0
- jac_coder/tool/impl/guarded.impl.jac +72 -0
- jac_coder/tool/impl/jac_analyzer.impl.jac +593 -0
- jac_coder/tool/impl/jac_docs.impl.jac +136 -0
- jac_coder/tool/impl/jac_tools.impl.jac +79 -0
- jac_coder/tool/impl/mcp.impl.jac +32 -0
- jac_coder/tool/impl/preview.impl.jac +233 -0
- jac_coder/tool/impl/question.impl.jac +29 -0
- jac_coder/tool/impl/scaffold.impl.jac +231 -0
- jac_coder/tool/impl/search.impl.jac +85 -0
- jac_coder/tool/impl/shell.impl.jac +89 -0
- jac_coder/tool/impl/task.impl.jac +12 -0
- jac_coder/tool/impl/think.impl.jac +4 -0
- jac_coder/tool/impl/todo.impl.jac +58 -0
- jac_coder/tool/impl/validate.impl.jac +236 -0
- jac_coder/tool/impl/web.impl.jac +91 -0
- jac_coder/tool/jac_analyzer.jac +21 -0
- jac_coder/tool/jac_docs.jac +9 -0
- jac_coder/tool/jac_tools.jac +11 -0
- jac_coder/tool/mcp.jac +17 -0
- jac_coder/tool/preview.jac +31 -0
- jac_coder/tool/question.jac +7 -0
- jac_coder/tool/scaffold.jac +10 -0
- jac_coder/tool/search.jac +14 -0
- jac_coder/tool/shell.jac +12 -0
- jac_coder/tool/task.jac +9 -0
- jac_coder/tool/think.jac +5 -0
- jac_coder/tool/todo.jac +12 -0
- jac_coder/tool/validate.jac +11 -0
- jac_coder/tool/vision.jac +17 -0
- jac_coder/tool/web.jac +10 -0
- jac_coder/util/__init__.jac +18 -0
- jac_coder/util/colors.jac +20 -0
- jac_coder/util/impl/sandbox.impl.jac +38 -0
- jac_coder/util/impl/tool_output.impl.jac +208 -0
- jac_coder/util/sandbox.jac +8 -0
- jac_coder/util/tool_output.jac +29 -0
- jac_coder/walkers.jac +67 -0
- jac_coder-0.1.0.dist-info/METADATA +9 -0
- jac_coder-0.1.0.dist-info/RECORD +85 -0
- jac_coder-0.1.0.dist-info/WHEEL +5 -0
- jac_coder-0.1.0.dist-info/entry_points.txt +3 -0
- jac_coder-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
# Core Jac Pitfalls — WRONG → RIGHT
|
|
2
|
+
|
|
3
|
+
> Jac is NOT Python. These are the mistakes LLMs consistently make.
|
|
4
|
+
> Read every entry. Each one will save you a broken build.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Semicolons are required on ALL statements
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
WRONG:
|
|
12
|
+
x = 5
|
|
13
|
+
print(x)
|
|
14
|
+
|
|
15
|
+
RIGHT:
|
|
16
|
+
x = 5;
|
|
17
|
+
print(x);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. Braces for blocks, not indentation
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
WRONG:
|
|
26
|
+
if x > 5:
|
|
27
|
+
print(x)
|
|
28
|
+
|
|
29
|
+
RIGHT:
|
|
30
|
+
if x > 5 {
|
|
31
|
+
print(x);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Import syntax
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
WRONG (Python):
|
|
41
|
+
from os import path
|
|
42
|
+
|
|
43
|
+
WRONG (deprecated Jac v1 — NEVER use):
|
|
44
|
+
import:py from os { path }
|
|
45
|
+
|
|
46
|
+
RIGHT:
|
|
47
|
+
import from os { path }
|
|
48
|
+
import from typing { Any }
|
|
49
|
+
import from datetime { datetime }
|
|
50
|
+
import os;
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The `import:py` prefix is **removed**. All imports use plain `import`. Never generate `import:py` or `include:jac`.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. Use `obj` not `class`
|
|
58
|
+
|
|
59
|
+
`obj` auto-generates `__init__`, `__eq__`, `__repr__`. Prefer it always.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
WRONG (Python):
|
|
63
|
+
class Foo:
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
RIGHT:
|
|
67
|
+
obj Foo {
|
|
68
|
+
has x: int = 5;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For graph programming, use `node`, `edge`, `walker` archetypes instead of `obj`.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 5. `def` for methods, `can` ONLY with `with` clause
|
|
77
|
+
|
|
78
|
+
The compiler enforces this: *"Expected 'with' after 'can' ability name (use 'def' for function-style declarations)"*
|
|
79
|
+
|
|
80
|
+
```jac
|
|
81
|
+
# WRONG — can without with clause
|
|
82
|
+
obj Foo {
|
|
83
|
+
can do_stuff() -> None { ... }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# RIGHT — def for regular methods
|
|
87
|
+
obj Foo {
|
|
88
|
+
has x: int = 0;
|
|
89
|
+
def do_stuff() -> None { print(self.x); }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# RIGHT — can ONLY for walker/node event abilities
|
|
93
|
+
walker MyWalker {
|
|
94
|
+
can process with MyNode entry {
|
|
95
|
+
report here.value;
|
|
96
|
+
visit [-->];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 6. `self` is implicit — NEVER in parameter list
|
|
104
|
+
|
|
105
|
+
`self` is available in the method body but NOT declared as a parameter.
|
|
106
|
+
|
|
107
|
+
```jac
|
|
108
|
+
# WRONG
|
|
109
|
+
obj Foo {
|
|
110
|
+
has x: int = 0;
|
|
111
|
+
def get_x(self) -> int { return self.x; }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# RIGHT
|
|
115
|
+
obj Foo {
|
|
116
|
+
has x: int = 0;
|
|
117
|
+
def get_x() -> int { return self.x; }
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 7. Constructor is `def init`, not `__init__`
|
|
124
|
+
|
|
125
|
+
Must call `super.init()` explicitly.
|
|
126
|
+
|
|
127
|
+
```jac
|
|
128
|
+
# WRONG
|
|
129
|
+
obj Foo {
|
|
130
|
+
def __init__(self, x: int) {
|
|
131
|
+
self.x = x;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# RIGHT
|
|
136
|
+
obj Foo {
|
|
137
|
+
has x: int;
|
|
138
|
+
def init(x: int) {
|
|
139
|
+
super.init();
|
|
140
|
+
self.x = x;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Note: If you only need default field values, skip `def init` entirely — `has` fields handle it:
|
|
146
|
+
|
|
147
|
+
```jac
|
|
148
|
+
obj Foo {
|
|
149
|
+
has x: int = 0;
|
|
150
|
+
has name: str = "";
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 8. Instance variables use `has`, not `self.x = ...`
|
|
157
|
+
|
|
158
|
+
```jac
|
|
159
|
+
# WRONG
|
|
160
|
+
obj Foo {
|
|
161
|
+
def init() {
|
|
162
|
+
self.x = 5;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
# RIGHT
|
|
167
|
+
obj Foo {
|
|
168
|
+
has x: int = 5;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## 9. `enumerate()` requires parentheses for tuple unpacking
|
|
175
|
+
|
|
176
|
+
```jac
|
|
177
|
+
# WRONG
|
|
178
|
+
for i, x in enumerate(items) {
|
|
179
|
+
print(i, x);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
# RIGHT
|
|
183
|
+
for (i, x) in enumerate(items) {
|
|
184
|
+
print(i, x);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
# Same for dict.items()
|
|
188
|
+
for (k, v) in my_dict.items() {
|
|
189
|
+
print(k, v);
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 10. Backtick escaping for keywords as identifiers
|
|
196
|
+
|
|
197
|
+
```jac
|
|
198
|
+
has `type: str; # "type" is a keyword — backtick escapes it
|
|
199
|
+
`edge = 5; # "edge" is a keyword
|
|
200
|
+
|
|
201
|
+
# Keywords that commonly need backtick:
|
|
202
|
+
# type, edge, node, obj, test, default, case, visit, spawn, entry, exit
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**These do NOT need backtick** — they are built-in references, not identifiers:
|
|
206
|
+
`self`, `super`, `root`, `here`, `visitor`, `init`, `postinit`
|
|
207
|
+
|
|
208
|
+
```jac
|
|
209
|
+
# WRONG
|
|
210
|
+
`self.name = "Alice";
|
|
211
|
+
`root ++> node;
|
|
212
|
+
|
|
213
|
+
# RIGHT
|
|
214
|
+
self.name = "Alice";
|
|
215
|
+
root ++> node;
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 11. `static def` for static methods
|
|
221
|
+
|
|
222
|
+
```jac
|
|
223
|
+
obj Foo {
|
|
224
|
+
static def bar() -> int {
|
|
225
|
+
return 42;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 12. `glob` for module-level variables
|
|
233
|
+
|
|
234
|
+
```jac
|
|
235
|
+
glob MAX_SIZE: int = 100;
|
|
236
|
+
glob config: dict = {};
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## 13. `with entry` — module entry point
|
|
242
|
+
|
|
243
|
+
Replaces Python's `if __name__ == "__main__"`.
|
|
244
|
+
|
|
245
|
+
```jac
|
|
246
|
+
with entry {
|
|
247
|
+
print("Hello, World!");
|
|
248
|
+
root spawn MyWalker();
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 14. Type annotations required on `has` and function signatures
|
|
255
|
+
|
|
256
|
+
```jac
|
|
257
|
+
has x: int = 5;
|
|
258
|
+
has name: str = "";
|
|
259
|
+
has items: list[str] = [];
|
|
260
|
+
has mapping: dict[str, int] = {};
|
|
261
|
+
has data: dict | None = None;
|
|
262
|
+
|
|
263
|
+
def greet(name: str, count: int = 1) -> str {
|
|
264
|
+
return f"Hello, {name}!";
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## 15. Control flow uses braces and colons for match/case
|
|
271
|
+
|
|
272
|
+
```jac
|
|
273
|
+
if x > 0 { print("pos"); }
|
|
274
|
+
elif x == 0 { print("zero"); }
|
|
275
|
+
else { print("neg"); }
|
|
276
|
+
|
|
277
|
+
for item in items { print(item); }
|
|
278
|
+
while count < 10 { count += 1; }
|
|
279
|
+
|
|
280
|
+
match value {
|
|
281
|
+
case "add":
|
|
282
|
+
result = a + b;
|
|
283
|
+
case _:
|
|
284
|
+
result = 0;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
try { risky(); }
|
|
288
|
+
except ValueError as e { print(f"Error: {e}"); }
|
|
289
|
+
finally { cleanup(); }
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 16. No `pass` — use empty braces or placeholder
|
|
295
|
+
|
|
296
|
+
```jac
|
|
297
|
+
# WRONG
|
|
298
|
+
if condition:
|
|
299
|
+
pass
|
|
300
|
+
|
|
301
|
+
# RIGHT
|
|
302
|
+
if condition {}
|
|
303
|
+
|
|
304
|
+
# Or with placeholder
|
|
305
|
+
_unused = 0;
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## 17. Tuple unpacking needs parentheses
|
|
311
|
+
|
|
312
|
+
```jac
|
|
313
|
+
# WRONG
|
|
314
|
+
x, y = func();
|
|
315
|
+
return a, b;
|
|
316
|
+
|
|
317
|
+
# RIGHT
|
|
318
|
+
(x, y) = func();
|
|
319
|
+
return (a, b);
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 18. Walker definition and traversal
|
|
325
|
+
|
|
326
|
+
```jac
|
|
327
|
+
# WRONG (no visit, no with clause)
|
|
328
|
+
walker MyWalker {
|
|
329
|
+
visit node.children;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
# RIGHT
|
|
333
|
+
walker MyWalker {
|
|
334
|
+
can visit_node with SomeNode entry {
|
|
335
|
+
print(here.name);
|
|
336
|
+
visit [-->]; # visit all outgoing nodes
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
# Spawn a walker
|
|
341
|
+
result = root spawn MyWalker();
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 19. Node and edge definitions
|
|
347
|
+
|
|
348
|
+
```jac
|
|
349
|
+
node City {
|
|
350
|
+
has name: str;
|
|
351
|
+
has population: int = 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
edge Road {
|
|
355
|
+
has distance: float = 0.0;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
# Connect nodes
|
|
359
|
+
a ++> b; # default edge
|
|
360
|
+
a +>:Road(distance=100.0):+> b; # typed edge
|
|
361
|
+
|
|
362
|
+
# Query
|
|
363
|
+
cities = [-->][?:City]; # all connected City nodes
|
|
364
|
+
filtered = [-->][?:City](?name == "NYC"); # with filter
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## 20. Graph keywords: here, visitor, self, root
|
|
370
|
+
|
|
371
|
+
| Keyword | Meaning | Used In |
|
|
372
|
+
|---------|---------|---------|
|
|
373
|
+
| `here` | Current node being visited | Walker abilities |
|
|
374
|
+
| `visitor` | The walker visiting this node | Node abilities |
|
|
375
|
+
| `self` | The archetype instance itself | Any method |
|
|
376
|
+
| `root` | Graph root node | Anywhere |
|
|
377
|
+
|
|
378
|
+
```jac
|
|
379
|
+
walker Collector {
|
|
380
|
+
can collect with DataNode entry {
|
|
381
|
+
# here = the DataNode, self = the walker
|
|
382
|
+
self.items.append(here.value);
|
|
383
|
+
visit [-->];
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
node DataNode {
|
|
388
|
+
has value: int;
|
|
389
|
+
can respond with Collector entry {
|
|
390
|
+
# here = this node, visitor = the Collector walker
|
|
391
|
+
print(f"Walker visiting me with {len(visitor.items)} items");
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 21. `disengage` vs `return` in walkers
|
|
399
|
+
|
|
400
|
+
- `return` — exits current ability, walker continues to next queued node
|
|
401
|
+
- `disengage` — stops walker entirely, no more traversal
|
|
402
|
+
|
|
403
|
+
```jac
|
|
404
|
+
walker Search {
|
|
405
|
+
can check with Item entry {
|
|
406
|
+
if here.name == self.target {
|
|
407
|
+
report here;
|
|
408
|
+
disengage; # found it, stop everything
|
|
409
|
+
}
|
|
410
|
+
visit [-->]; # keep searching
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## 22. `report` emits data from walkers
|
|
418
|
+
|
|
419
|
+
```jac
|
|
420
|
+
walker GetData {
|
|
421
|
+
can fetch with Root entry {
|
|
422
|
+
report {"items": [1, 2, 3]};
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
# Access reported data
|
|
427
|
+
result = root spawn GetData();
|
|
428
|
+
data = result.reports[0];
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## 23. Interface/implementation separation
|
|
434
|
+
|
|
435
|
+
Declaration (`.jac` file) — signatures end with `;`:
|
|
436
|
+
|
|
437
|
+
```jac
|
|
438
|
+
obj Calculator {
|
|
439
|
+
has result: float = 0.0;
|
|
440
|
+
def add(x: float) -> float;
|
|
441
|
+
def reset() -> None;
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Implementation (`impl/` subdirectory, `.impl.jac` file):
|
|
446
|
+
|
|
447
|
+
```jac
|
|
448
|
+
impl Calculator.add(x: float) -> float {
|
|
449
|
+
self.result += x;
|
|
450
|
+
return self.result;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
impl Calculator.reset() -> None {
|
|
454
|
+
self.result = 0.0;
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
**CRITICAL: A parse error in `.impl.jac` breaks the ENTIRE file.** All implementations in that file will have 0 body items. Always check syntax carefully.
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## 24. `by llm()` for AI-powered functions
|
|
463
|
+
|
|
464
|
+
**CRITICAL: You MUST import byllm and create a glob model before using `by llm()`.**
|
|
465
|
+
|
|
466
|
+
```jac
|
|
467
|
+
# STEP 1: Import and create model (REQUIRED)
|
|
468
|
+
import from byllm.lib { Model }
|
|
469
|
+
|
|
470
|
+
glob llm: Model = Model(model_name="gpt-4o");
|
|
471
|
+
|
|
472
|
+
# STEP 2: Use by llm() on functions
|
|
473
|
+
# Simple — LLM infers from function name and types
|
|
474
|
+
def classify_sentiment(text: str) -> str by llm();
|
|
475
|
+
|
|
476
|
+
# With tools (triggers ReAct loop)
|
|
477
|
+
def respond(message: str, history: list[dict]) -> str by llm(
|
|
478
|
+
tools=[read_file, search],
|
|
479
|
+
max_react_iterations=10,
|
|
480
|
+
temperature=0.2
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
# Semantic annotations — system prompt for by llm()
|
|
484
|
+
sem MyAgent.respond = """You are an expert assistant.
|
|
485
|
+
Use tools to answer thoroughly.""";
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
Without the `import from byllm.lib { Model }` and `glob llm: Model = Model(...)`, any `by llm()` call will fail.
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## 25. Access modifiers
|
|
493
|
+
|
|
494
|
+
| Modifier | Meaning |
|
|
495
|
+
|----------|---------|
|
|
496
|
+
| `:pub` | Public — REST endpoint, importable |
|
|
497
|
+
| `:priv` | Private — requires auth, per-user data |
|
|
498
|
+
| `:protect` | Protected — module-internal only |
|
|
499
|
+
| *(none)* | Default — module-scoped |
|
|
500
|
+
|
|
501
|
+
```jac
|
|
502
|
+
walker :pub get_items { ... } # Public API endpoint
|
|
503
|
+
walker :priv add_item { ... } # Authenticated endpoint
|
|
504
|
+
def :protect validate(x: str) -> bool { ... } # Internal helper
|
|
505
|
+
def:pub get_todos() -> list { ... } # Public function endpoint
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## 26. Enum definition
|
|
511
|
+
|
|
512
|
+
```jac
|
|
513
|
+
enum Color {
|
|
514
|
+
RED = "red",
|
|
515
|
+
GREEN = "green",
|
|
516
|
+
BLUE = "blue"
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
enum Direction { NORTH, SOUTH, EAST, WEST }
|
|
520
|
+
|
|
521
|
+
def describe(c: Color) -> str {
|
|
522
|
+
return f"The color is {c.value}";
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
## 27. Test blocks
|
|
529
|
+
|
|
530
|
+
```jac
|
|
531
|
+
test "addition works" {
|
|
532
|
+
calc = Calculator();
|
|
533
|
+
calc.add(5.0);
|
|
534
|
+
assert calc.get_result() == 5.0;
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Always provide default values for `has` fields
|
|
540
|
+
|
|
541
|
+
```
|
|
542
|
+
WRONG — fields without defaults crash on construction:
|
|
543
|
+
node Project {
|
|
544
|
+
has title: str;
|
|
545
|
+
has tags: list;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
RIGHT — every field has a default:
|
|
549
|
+
node Project {
|
|
550
|
+
has title: str = "";
|
|
551
|
+
has tags: list = [];
|
|
552
|
+
has count: int = 0;
|
|
553
|
+
has price: float = 0.0;
|
|
554
|
+
has active: bool = False;
|
|
555
|
+
has meta: dict = {};
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
---
|