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.
Files changed (85) hide show
  1. jac_coder/__init__.jac +0 -0
  2. jac_coder/api.jac +82 -0
  3. jac_coder/cli_entry.py +25 -0
  4. jac_coder/config.jac +36 -0
  5. jac_coder/context.jac +17 -0
  6. jac_coder/data/examples/ai_agent.md +90 -0
  7. jac_coder/data/examples/blog_app.md +386 -0
  8. jac_coder/data/examples/core_patterns.md +321 -0
  9. jac_coder/data/examples/todo_app.md +321 -0
  10. jac_coder/data/reference/ai.md +131 -0
  11. jac_coder/data/reference/backend.md +215 -0
  12. jac_coder/data/reference/frontend.md +271 -0
  13. jac_coder/data/reference/osp.md +229 -0
  14. jac_coder/data/reference/pitfalls.md +141 -0
  15. jac_coder/data/reference/syntax.md +159 -0
  16. jac_coder/data/rules/core_jac.md +559 -0
  17. jac_coder/data/rules/fullstack.md +362 -0
  18. jac_coder/data/rules/workflow.md +88 -0
  19. jac_coder/events.jac +110 -0
  20. jac_coder/impl/api.impl.jac +399 -0
  21. jac_coder/impl/config.impl.jac +163 -0
  22. jac_coder/impl/context.impl.jac +117 -0
  23. jac_coder/impl/mcp_manager.impl.jac +380 -0
  24. jac_coder/impl/memory.impl.jac +247 -0
  25. jac_coder/impl/nodes.impl.jac +259 -0
  26. jac_coder/impl/permission.impl.jac +62 -0
  27. jac_coder/impl/walkers.impl.jac +298 -0
  28. jac_coder/mcp_manager.jac +35 -0
  29. jac_coder/memory.jac +15 -0
  30. jac_coder/nodes.jac +306 -0
  31. jac_coder/permission.jac +19 -0
  32. jac_coder/serve_entry.jac +30 -0
  33. jac_coder/server.jac +324 -0
  34. jac_coder/tool/__init__.jac +17 -0
  35. jac_coder/tool/checked.jac +10 -0
  36. jac_coder/tool/delegation.jac +23 -0
  37. jac_coder/tool/filesystem.jac +25 -0
  38. jac_coder/tool/git.jac +18 -0
  39. jac_coder/tool/guarded.jac +23 -0
  40. jac_coder/tool/impl/checked.impl.jac +38 -0
  41. jac_coder/tool/impl/delegation.impl.jac +157 -0
  42. jac_coder/tool/impl/filesystem.impl.jac +781 -0
  43. jac_coder/tool/impl/git.impl.jac +115 -0
  44. jac_coder/tool/impl/guarded.impl.jac +72 -0
  45. jac_coder/tool/impl/jac_analyzer.impl.jac +593 -0
  46. jac_coder/tool/impl/jac_docs.impl.jac +136 -0
  47. jac_coder/tool/impl/jac_tools.impl.jac +79 -0
  48. jac_coder/tool/impl/mcp.impl.jac +32 -0
  49. jac_coder/tool/impl/preview.impl.jac +233 -0
  50. jac_coder/tool/impl/question.impl.jac +29 -0
  51. jac_coder/tool/impl/scaffold.impl.jac +231 -0
  52. jac_coder/tool/impl/search.impl.jac +85 -0
  53. jac_coder/tool/impl/shell.impl.jac +89 -0
  54. jac_coder/tool/impl/task.impl.jac +12 -0
  55. jac_coder/tool/impl/think.impl.jac +4 -0
  56. jac_coder/tool/impl/todo.impl.jac +58 -0
  57. jac_coder/tool/impl/validate.impl.jac +236 -0
  58. jac_coder/tool/impl/web.impl.jac +91 -0
  59. jac_coder/tool/jac_analyzer.jac +21 -0
  60. jac_coder/tool/jac_docs.jac +9 -0
  61. jac_coder/tool/jac_tools.jac +11 -0
  62. jac_coder/tool/mcp.jac +17 -0
  63. jac_coder/tool/preview.jac +31 -0
  64. jac_coder/tool/question.jac +7 -0
  65. jac_coder/tool/scaffold.jac +10 -0
  66. jac_coder/tool/search.jac +14 -0
  67. jac_coder/tool/shell.jac +12 -0
  68. jac_coder/tool/task.jac +9 -0
  69. jac_coder/tool/think.jac +5 -0
  70. jac_coder/tool/todo.jac +12 -0
  71. jac_coder/tool/validate.jac +11 -0
  72. jac_coder/tool/vision.jac +17 -0
  73. jac_coder/tool/web.jac +10 -0
  74. jac_coder/util/__init__.jac +18 -0
  75. jac_coder/util/colors.jac +20 -0
  76. jac_coder/util/impl/sandbox.impl.jac +38 -0
  77. jac_coder/util/impl/tool_output.impl.jac +208 -0
  78. jac_coder/util/sandbox.jac +8 -0
  79. jac_coder/util/tool_output.jac +29 -0
  80. jac_coder/walkers.jac +67 -0
  81. jac_coder-0.1.0.dist-info/METADATA +9 -0
  82. jac_coder-0.1.0.dist-info/RECORD +85 -0
  83. jac_coder-0.1.0.dist-info/WHEEL +5 -0
  84. jac_coder-0.1.0.dist-info/entry_points.txt +3 -0
  85. 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
+ ---