jac-coder 0.1.4__tar.gz → 0.1.5__tar.gz

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 (219) hide show
  1. {jac_coder-0.1.4 → jac_coder-0.1.5}/PKG-INFO +1 -1
  2. jac_coder-0.1.5/jac_coder/_precompiled/cpython-312/cost_tracker.jir +0 -0
  3. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/scaffold.jir +0 -0
  4. jac_coder-0.1.5/jac_coder/_precompiled/cpython-313/cost_tracker.jir +0 -0
  5. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/scaffold.jir +0 -0
  6. jac_coder-0.1.5/jac_coder/_precompiled/cpython-314/cost_tracker.jir +0 -0
  7. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/scaffold.jir +0 -0
  8. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/manifest.json +2 -2
  9. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/examples/blog_app.md +6 -7
  10. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/reference/frontend.md +12 -8
  11. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/reference/pitfalls.md +4 -4
  12. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/rules/fullstack.md +16 -10
  13. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/cost_tracker.impl.jac +16 -11
  14. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/scaffold.impl.jac +5 -5
  15. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder.egg-info/PKG-INFO +1 -1
  16. {jac_coder-0.1.4 → jac_coder-0.1.5}/pyproject.toml +1 -1
  17. jac_coder-0.1.4/jac_coder/_precompiled/cpython-312/cost_tracker.jir +0 -0
  18. jac_coder-0.1.4/jac_coder/_precompiled/cpython-313/cost_tracker.jir +0 -0
  19. jac_coder-0.1.4/jac_coder/_precompiled/cpython-314/cost_tracker.jir +0 -0
  20. {jac_coder-0.1.4 → jac_coder-0.1.5}/README.md +0 -0
  21. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/__init__.jac +0 -0
  22. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/__init__.py +0 -0
  23. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/__init__.jir +0 -0
  24. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/api.jir +0 -0
  25. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/config.jir +0 -0
  26. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/context.jir +0 -0
  27. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/events.jir +0 -0
  28. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/mcp_manager.jir +0 -0
  29. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/memory.jir +0 -0
  30. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/nodes.jir +0 -0
  31. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/permission.jir +0 -0
  32. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/prompt.jir +0 -0
  33. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/serve_entry.jir +0 -0
  34. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/server.jir +0 -0
  35. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/__init__.jir +0 -0
  36. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/checked.jir +0 -0
  37. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/delegation.jir +0 -0
  38. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/filesystem.jir +0 -0
  39. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/git.jir +0 -0
  40. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/guarded.jir +0 -0
  41. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/jac_analyzer.jir +0 -0
  42. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/jac_docs.jir +0 -0
  43. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/jac_tools.jir +0 -0
  44. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/mcp.jir +0 -0
  45. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/preview.jir +0 -0
  46. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/question.jir +0 -0
  47. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/search.jir +0 -0
  48. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/shell.jir +0 -0
  49. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/task.jir +0 -0
  50. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/think.jir +0 -0
  51. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/todo.jir +0 -0
  52. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/validate.jir +0 -0
  53. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/web.jir +0 -0
  54. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/__init__.jir +0 -0
  55. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/colors.jir +0 -0
  56. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/sandbox.jir +0 -0
  57. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/tool_output.jir +0 -0
  58. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/walkers.jir +0 -0
  59. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/__init__.jir +0 -0
  60. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/api.jir +0 -0
  61. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/config.jir +0 -0
  62. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/context.jir +0 -0
  63. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/events.jir +0 -0
  64. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/mcp_manager.jir +0 -0
  65. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/memory.jir +0 -0
  66. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/nodes.jir +0 -0
  67. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/permission.jir +0 -0
  68. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/prompt.jir +0 -0
  69. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/serve_entry.jir +0 -0
  70. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/server.jir +0 -0
  71. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/__init__.jir +0 -0
  72. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/checked.jir +0 -0
  73. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/delegation.jir +0 -0
  74. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/filesystem.jir +0 -0
  75. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/git.jir +0 -0
  76. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/guarded.jir +0 -0
  77. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/jac_analyzer.jir +0 -0
  78. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/jac_docs.jir +0 -0
  79. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/jac_tools.jir +0 -0
  80. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/mcp.jir +0 -0
  81. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/preview.jir +0 -0
  82. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/question.jir +0 -0
  83. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/search.jir +0 -0
  84. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/shell.jir +0 -0
  85. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/task.jir +0 -0
  86. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/think.jir +0 -0
  87. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/todo.jir +0 -0
  88. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/validate.jir +0 -0
  89. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/web.jir +0 -0
  90. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/__init__.jir +0 -0
  91. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/colors.jir +0 -0
  92. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/sandbox.jir +0 -0
  93. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/tool_output.jir +0 -0
  94. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/walkers.jir +0 -0
  95. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/__init__.jir +0 -0
  96. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/api.jir +0 -0
  97. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/config.jir +0 -0
  98. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/context.jir +0 -0
  99. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/events.jir +0 -0
  100. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/mcp_manager.jir +0 -0
  101. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/memory.jir +0 -0
  102. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/nodes.jir +0 -0
  103. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/permission.jir +0 -0
  104. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/prompt.jir +0 -0
  105. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/serve_entry.jir +0 -0
  106. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/server.jir +0 -0
  107. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/__init__.jir +0 -0
  108. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/checked.jir +0 -0
  109. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/delegation.jir +0 -0
  110. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/filesystem.jir +0 -0
  111. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/git.jir +0 -0
  112. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/guarded.jir +0 -0
  113. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/jac_analyzer.jir +0 -0
  114. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/jac_docs.jir +0 -0
  115. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/jac_tools.jir +0 -0
  116. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/mcp.jir +0 -0
  117. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/preview.jir +0 -0
  118. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/question.jir +0 -0
  119. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/search.jir +0 -0
  120. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/shell.jir +0 -0
  121. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/task.jir +0 -0
  122. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/think.jir +0 -0
  123. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/todo.jir +0 -0
  124. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/validate.jir +0 -0
  125. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/web.jir +0 -0
  126. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/__init__.jir +0 -0
  127. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/colors.jir +0 -0
  128. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/sandbox.jir +0 -0
  129. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/tool_output.jir +0 -0
  130. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/walkers.jir +0 -0
  131. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/api.jac +0 -0
  132. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/cli_entry.py +0 -0
  133. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/config.jac +0 -0
  134. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/context.jac +0 -0
  135. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/cost_tracker.jac +0 -0
  136. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/examples/ai_agent.md +0 -0
  137. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/examples/core_patterns.md +0 -0
  138. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/examples/todo_app.md +0 -0
  139. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/reference/ai.md +0 -0
  140. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/reference/backend.md +0 -0
  141. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/reference/osp.md +0 -0
  142. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/reference/syntax.md +0 -0
  143. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/rules/core_jac.md +0 -0
  144. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/data/rules/workflow.md +0 -0
  145. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/events.jac +0 -0
  146. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/api.impl.jac +0 -0
  147. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/config.impl.jac +0 -0
  148. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/context.impl.jac +0 -0
  149. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/mcp_manager.impl.jac +0 -0
  150. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/memory.impl.jac +0 -0
  151. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/nodes.impl.jac +0 -0
  152. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/permission.impl.jac +0 -0
  153. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/prompt.impl.jac +0 -0
  154. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/impl/walkers.impl.jac +0 -0
  155. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/mcp_manager.jac +0 -0
  156. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/memory.jac +0 -0
  157. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/nodes.jac +0 -0
  158. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/permission.jac +0 -0
  159. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/prompt.jac +0 -0
  160. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/serve_entry.jac +0 -0
  161. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/server.jac +0 -0
  162. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/__init__.jac +0 -0
  163. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/checked.jac +0 -0
  164. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/delegation.jac +0 -0
  165. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/filesystem.jac +0 -0
  166. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/git.jac +0 -0
  167. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/guarded.jac +0 -0
  168. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/checked.impl.jac +0 -0
  169. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/delegation.impl.jac +0 -0
  170. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/filesystem.impl.jac +0 -0
  171. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/git.impl.jac +0 -0
  172. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/guarded.impl.jac +0 -0
  173. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/jac_analyzer.impl.jac +0 -0
  174. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/jac_docs.impl.jac +0 -0
  175. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/jac_tools.impl.jac +0 -0
  176. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/mcp.impl.jac +0 -0
  177. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/preview.impl.jac +0 -0
  178. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/question.impl.jac +0 -0
  179. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/search.impl.jac +0 -0
  180. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/shell.impl.jac +0 -0
  181. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/task.impl.jac +0 -0
  182. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/think.impl.jac +0 -0
  183. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/todo.impl.jac +0 -0
  184. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/validate.impl.jac +0 -0
  185. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/impl/web.impl.jac +0 -0
  186. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/jac_analyzer.jac +0 -0
  187. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/jac_docs.jac +0 -0
  188. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/jac_tools.jac +0 -0
  189. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/mcp.jac +0 -0
  190. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/preview.jac +0 -0
  191. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/question.jac +0 -0
  192. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/scaffold.jac +0 -0
  193. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/search.jac +0 -0
  194. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/shell.jac +0 -0
  195. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/task.jac +0 -0
  196. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/think.jac +0 -0
  197. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/todo.jac +0 -0
  198. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/validate.jac +0 -0
  199. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/tool/web.jac +0 -0
  200. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/util/__init__.jac +0 -0
  201. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/util/colors.jac +0 -0
  202. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/util/impl/sandbox.impl.jac +0 -0
  203. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/util/impl/tool_output.impl.jac +0 -0
  204. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/util/sandbox.jac +0 -0
  205. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/util/tool_output.jac +0 -0
  206. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder/walkers.jac +0 -0
  207. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder.egg-info/SOURCES.txt +0 -0
  208. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder.egg-info/dependency_links.txt +0 -0
  209. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder.egg-info/entry_points.txt +0 -0
  210. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder.egg-info/requires.txt +0 -0
  211. {jac_coder-0.1.4 → jac_coder-0.1.5}/jac_coder.egg-info/top_level.txt +0 -0
  212. {jac_coder-0.1.4 → jac_coder-0.1.5}/setup.cfg +0 -0
  213. {jac_coder-0.1.4 → jac_coder-0.1.5}/tests/test_context.py +0 -0
  214. {jac_coder-0.1.4 → jac_coder-0.1.5}/tests/test_events.py +0 -0
  215. {jac_coder-0.1.4 → jac_coder-0.1.5}/tests/test_graph.py +0 -0
  216. {jac_coder-0.1.4 → jac_coder-0.1.5}/tests/test_interact.py +0 -0
  217. {jac_coder-0.1.4 → jac_coder-0.1.5}/tests/test_memory.py +0 -0
  218. {jac_coder-0.1.4 → jac_coder-0.1.5}/tests/test_selfcorrect.py +0 -0
  219. {jac_coder-0.1.4 → jac_coder-0.1.5}/tests/test_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jac-coder
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: AI coding agent backend for Jac, powered by jac-byllm
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: python-dotenv>=1.0.0
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "cost_tracker.jac": {
25
25
  "impl_hashes": {
26
- "impl/cost_tracker.impl.jac": "c7679953be4b6a4e4697575f3fd8e2b9467c294ca341c7584a253cd6ad447889"
26
+ "impl/cost_tracker.impl.jac": "f6fc36660b31917b93f3a73b44aaaa340e024e45b9a855dbfc9e35f713a52032"
27
27
  },
28
28
  "source_hash": "41f2358725b03d093102da10138b9334e04e36d600b1fff1e13566b434c70179"
29
29
  },
@@ -137,7 +137,7 @@
137
137
  },
138
138
  "tool/scaffold.jac": {
139
139
  "impl_hashes": {
140
- "tool/impl/scaffold.impl.jac": "b4dcc0b46e7d844d5cbf6aa5a2109fa2f265b184332052d5cbc4b768710e7988"
140
+ "tool/impl/scaffold.impl.jac": "1e465d3a37c2f63638a12876d490cd9384a47479152a85fc8373a12bf0b8505a"
141
141
  },
142
142
  "source_hash": "ebb6d09098f1941aa4baf9f54541bef6a0e430b32549feda0d4021448e4a12d8"
143
143
  },
@@ -121,7 +121,6 @@ def:pub add_comment(post_id: str, author: str, text: str) -> Comment {
121
121
  }
122
122
  }
123
123
  }
124
- }
125
124
 
126
125
  # --- Walker endpoint (single-request post + comments) ---
127
126
 
@@ -279,13 +278,13 @@ def:pub useComments(postId: str) -> dict {
279
278
  import from "@jac/runtime" { Link }
280
279
 
281
280
  def:pub PostCard(props: dict) -> JsxElement {
282
- onDelete = props.onDelete or None;
281
+ onDelete = props["onDelete"] or None;
283
282
 
284
283
  # Props are always dict — extract values
285
- postId = props.postId or "";
286
- title = props.title or "Untitled";
287
- body = props.body or "";
288
- category = props.category or "";
284
+ postId = props["postId"] or "";
285
+ title = props["title"] or "Untitled";
286
+ body = props["body"] or "";
287
+ category = props["category"] or "";
289
288
 
290
289
  preview = body;
291
290
  if len(body) > 150 { preview = body[0:150] + "..."; }
@@ -309,7 +308,7 @@ def:pub PostCard(props: dict) -> JsxElement {
309
308
  import from ..hooks.useComments { useComments }
310
309
 
311
310
  def:pub CommentList(props: dict) -> JsxElement {
312
- postId = props.postId or "";
311
+ postId = props["postId"] or "";
313
312
  data = useComments(postId);
314
313
  comments = data["comments"] or [];
315
314
 
@@ -7,7 +7,7 @@ Components are public functions returning `JsxElement`.
7
7
  ```jac
8
8
  # In a .cl.jac file:
9
9
  def:pub Header(props: dict) -> JsxElement {
10
- title = props.title or "";
10
+ title = props["title"] or "";
11
11
  return (
12
12
  <header className="border-b px-6 py-4">
13
13
  <h1 className="text-xl font-bold">{title}</h1>
@@ -45,8 +45,12 @@ cl def:pub app -> JsxElement {
45
45
  }
46
46
  }
47
47
 
48
+ def handle_input(e: any) -> None {
49
+ text = e.target.value;
50
+ }
51
+
48
52
  return <div>
49
- <input value={text} onChange={lambda e: any -> None { text = e.target.value; }} />
53
+ <input value={text} onChange={handle_input} />
50
54
  <button onClick={add}>Add</button>
51
55
  {[<p key={jid(t)}>{t.title}</p> for t in todos]}
52
56
  </div>;
@@ -88,7 +92,7 @@ NEVER use `useEffect` — use `can with entry` instead. NEVER import from react.
88
92
 
89
93
  ## Event Handlers
90
94
 
91
- ALL handlers must be named `def` functions defined BEFORE `return`. NEVER use lambda or inline def in JSX.
95
+ ALL handlers MUST be named `def` functions defined BEFORE `return`. NEVER use `lambda` or inline `def` in JSX.
92
96
 
93
97
  ```jac
94
98
  def:pub TodoList() -> JsxElement {
@@ -129,7 +133,7 @@ Use `jid(node)` to get the unique graph ID of a node object. Essential for React
129
133
  ## Typed objects vs props — where dot access works
130
134
 
131
135
  **Dot access** works on typed objects returned from API calls (via `sv import`).
132
- **Props are always `dict`** — use dict access (`props.title` or `props["title"]`).
136
+ **Props are always `dict`** — use bracket access (`props["title"]`). NEVER use dot access (`props.title`).
133
137
 
134
138
  ```jac
135
139
  # In hook — typed objects from API, dot access works
@@ -141,9 +145,9 @@ todos[0].title # dot access on typed object
141
145
 
142
146
  # Inside child component — props is a dict, NOT a typed object
143
147
  def:pub TodoItem(props: dict) -> JsxElement {
144
- title = props.title or ""; # props access (dict)
145
- completed = props.completed or False;
146
- todoId = props.todoId or "";
148
+ title = props["title"] or ""; # props access (dict)
149
+ completed = props["completed"] or False;
150
+ todoId = props["todoId"] or "";
147
151
  }
148
152
  ```
149
153
 
@@ -177,7 +181,7 @@ items = [item for item in items if item["id"] != targetId];
177
181
  <Button><span>7</span></Button>
178
182
  <Button><span>8</span></Button>
179
183
 
180
- # RIGHT — child component that renders via str(props.label)
184
+ # RIGHT — child component that renders via str(props["label"])
181
185
  {[<KeyBtn key={k["label"]} label={k["label"]} /> for k in keys]}
182
186
  ```
183
187
 
@@ -53,12 +53,12 @@ The #1 runtime crash in .cl.jac. Happens when accessing property on `undefined`.
53
53
 
54
54
  ```jac
55
55
  # WRONG — crashes if parent doesn't pass "items" prop
56
- items = props.items; # undefined!
56
+ items = props["items"]; # undefined!
57
57
  return <div>{[... for item in items]}</div>; # CRASH
58
58
 
59
59
  # RIGHT — always default props
60
- items = props.items or [];
61
- title = props.title or "";
60
+ items = props["items"] or [];
61
+ title = props["title"] or "";
62
62
 
63
63
  # WRONG — chaining on undefined
64
64
  data = result.reports[0].items; # CRASH if reports empty
@@ -122,7 +122,7 @@ keys = [{"label": "7", "onClick": h7}, {"label": "8", "onClick": h8}];
122
122
 
123
123
  # RIGHT — if you must loop, pass data as a prop to a child component
124
124
  {[<KeyButton key={k["label"]} label={k["label"]} onClick={k["onClick"]} /> for k in keys]}
125
- # Where KeyButton renders: <button onClick={props.onClick}><span>{str(props.label)}</span></button>
125
+ # Where KeyButton renders: <button onClick={props["onClick"]}><span>{str(props["label"])}</span></button>
126
126
  ```
127
127
 
128
128
  **Rule:** When rendering a list of elements with text content, either:
@@ -157,8 +157,8 @@ def:pub Header(title: str, theme: str) -> JsxElement { ... }
157
157
 
158
158
  # RIGHT — always use props: dict, destructure inside
159
159
  def:pub Header(props: dict) -> JsxElement {
160
- title = props.title or "";
161
- theme = props.theme or "light";
160
+ title = props["title"] or "";
161
+ theme = props["theme"] or "light";
162
162
  return <header>{title}</header>;
163
163
  }
164
164
 
@@ -226,23 +226,29 @@ can with exit { ... } # cleanup/unmount
226
226
 
227
227
  **NEVER use `useEffect(lambda...)` — that is OLD syntax.**
228
228
 
229
- ## Event handlers — prefer named functions, lambda OK for simple cases
229
+ ## Event handlers — ALWAYS use named functions
230
230
 
231
231
  ```jac
232
- # PREFERRED — named function ABOVE return, passed by name
232
+ # RIGHT — named function ABOVE return, passed by name
233
233
  def handle_click() -> None {
234
234
  count = count + 1;
235
235
  }
236
- return <button onClick={handle_click}>Click</button>;
236
+ def handle_input(e: any) -> None {
237
+ text = e.target.value;
238
+ }
239
+ return <div>
240
+ <button onClick={handle_click}>Click</button>
241
+ <input onChange={handle_input} />
242
+ </div>;
237
243
 
238
- # OK for simple one-liners — lambda with typed param
244
+ # WRONG — lambda in JSX
239
245
  <input onChange={lambda e: any -> None { text = e.target.value; }} />
240
246
 
241
- # WRONG — inline def (NOT lambda)
247
+ # WRONG — inline def in JSX
242
248
  <button onClick={def(e: any) -> None { count = count + 1; }}>
243
249
  ```
244
250
 
245
- Use named `def` handlers for complex logic. Lambda is fine for simple state updates like `onChange` on inputs. NEVER use `def` inline in JSX attributes.
251
+ NEVER use `lambda` or inline `def` in JSX attributes. ALWAYS define named `def` handlers BEFORE `return` and pass by name.
246
252
 
247
253
  ## Functions MUST be defined BEFORE return
248
254
 
@@ -378,8 +384,8 @@ name = item["name"] if item and "name" in item else "";
378
384
  {[<Card title={p["title"] if p and "title" in p else ""} /> for p in projects if p]}
379
385
 
380
386
  # Props — always default
381
- items = props.items or [];
382
- title = props.title or "";
387
+ items = props["items"] or [];
388
+ title = props["title"] or "";
383
389
  ```
384
390
 
385
391
  **CRITICAL: The `"key" in x` operator crashes if `x` is undefined.** Always write `x and "key" in x`.
@@ -3,18 +3,24 @@ impl record_usage(usage_data: dict, agent: str = "main") -> None {
3
3
  return;
4
4
  }
5
5
 
6
- total = usage_data.get("total", {});
7
6
  per_call = usage_data.get("per_call", []);
8
7
 
9
8
  with _lock {
10
- # Record each individual LLM call
9
+ # Record each individual LLM call and accumulate totals from per-call data
10
+ # (the top-level `total` dict often omits cached_tokens, so summing per-call
11
+ # is the reliable source of truth)
11
12
  for (i, call) in enumerate(per_call) {
12
13
  call_record = {
13
14
  "agent": agent,
14
15
  "iteration": len(_session_data["calls"]) + 1,
15
16
  "input_tokens": int(call.get("input_tokens", 0) or call.get("prompt_tokens", 0) or 0),
16
17
  "output_tokens": int(call.get("output_tokens", 0) or call.get("completion_tokens", 0) or 0),
17
- "cached_tokens": int(call.get("cached_tokens", 0) or call.get("cache_read_input_tokens", 0) or 0),
18
+ "cached_tokens": int(
19
+ call.get("cached_tokens", 0)
20
+ or call.get("cache_read_input_tokens", 0)
21
+ or (call.get("prompt_tokens_details") or {}).get("cached_tokens", 0)
22
+ or 0
23
+ ),
18
24
  "total_tokens": int(call.get("total_tokens", 0) or 0)
19
25
  };
20
26
  # Calculate total if not provided
@@ -22,15 +28,12 @@ impl record_usage(usage_data: dict, agent: str = "main") -> None {
22
28
  call_record["total_tokens"] = call_record["input_tokens"] + call_record["output_tokens"];
23
29
  }
24
30
  _session_data["calls"].append(call_record);
25
- }
26
31
 
27
- # Update running totals
28
- for key in ["input_tokens", "output_tokens", "cached_tokens", "total_tokens"] {
29
- val = int(total.get(key, 0) or total.get(
30
- {"input_tokens": "prompt_tokens", "output_tokens": "completion_tokens"}.get(key, key),
31
- 0
32
- ) or 0);
33
- _session_data["totals"][key] += val;
32
+ # Accumulate into running totals from this call
33
+ _session_data["totals"]["input_tokens"] += call_record["input_tokens"];
34
+ _session_data["totals"]["output_tokens"] += call_record["output_tokens"];
35
+ _session_data["totals"]["cached_tokens"] += call_record["cached_tokens"];
36
+ _session_data["totals"]["total_tokens"] += call_record["total_tokens"];
34
37
  }
35
38
  }
36
39
  }
@@ -41,6 +44,8 @@ impl get_summary() -> dict {
41
44
  num_calls = len(_session_data["calls"]);
42
45
  totals = dict(_session_data["totals"]);
43
46
  totals["num_calls"] = num_calls;
47
+ # Effective input tokens — input that wasn't served from cache, billed at full rate
48
+ totals["effective_input_tokens"] = max(totals["input_tokens"] - totals["cached_tokens"], 0);
44
49
  if num_calls > 0 {
45
50
  totals["avg_input_per_call"] = totals["input_tokens"] // num_calls;
46
51
  totals["avg_output_per_call"] = totals["output_tokens"] // num_calls;
@@ -117,11 +117,11 @@ glob _UTILS_CL = 'import from "clsx" { clsx }\nimport from "tailwind-merge" { tw
117
117
 
118
118
  glob _FRONTEND_MAIN = 'cl import from .components.Layout { Layout }\ncl {\n def:pub app() -> JsxElement {\n return <Layout />;\n }\n}\n';
119
119
 
120
- glob _FRONTEND_HEADER = 'import from ..lib.utils { cn }\n\ndef:pub Header(title: str, theme: str, on_toggle_theme: any) -> JsxElement {\n return (\n <header className="border-b border-border px-6 py-4 flex items-center justify-between">\n <h1 className="text-xl font-bold">{title}</h1>\n <button onClick={on_toggle_theme}\n className="px-3 py-1 bg-secondary text-secondary-foreground rounded-lg text-sm">\n {(theme == "dark") and "Light" or "Dark"}\n </button>\n </header>\n );\n}\n';
120
+ glob _FRONTEND_HEADER = 'import from ..lib.utils { cn }\n\ndef:pub Header(props: dict) -> JsxElement {\n # Props — extract from dict\n title = props["title"] or "";\n theme = props["theme"] or "light";\n on_toggle_theme = props["onToggleTheme"] or None;\n\n return (\n <header className="border-b border-border px-6 py-4 flex items-center justify-between">\n <h1 className="text-xl font-bold">{title}</h1>\n <button onClick={on_toggle_theme}\n className="px-3 py-1 bg-secondary text-secondary-foreground rounded-lg text-sm">\n {(theme == "dark") and "Light" or "Dark"}\n </button>\n </header>\n );\n}\n';
121
121
 
122
122
  glob _FRONTEND_COUNTER = 'import from ..lib.utils { cn }\n\ndef:pub Counter() -> JsxElement {\n # State\n has count: int = 0;\n\n # Handlers\n def handle_increment() -> None {\n count = count + 1;\n }\n\n # Render\n return (\n <button onClick={handle_increment}\n className="px-4 py-2 bg-primary text-primary-foreground rounded-lg">\n Count: {str(count)}\n </button>\n );\n}\n';
123
123
 
124
- glob _FRONTEND_APP = 'import "..styles.global.css";\nimport from .Header { Header }\nimport from .Counter { Counter }\n\ndef:pub Layout() -> JsxElement {\n # State\n has theme: str = "light";\n\n # Effects\n can with (theme) entry {\n if theme == "dark" {\n document.documentElement.classList.add("dark");\n } else {\n document.documentElement.classList.remove("dark");\n }\n }\n\n # Handlers\n def handle_toggle_theme() -> None {\n theme = (theme == "dark") and "light" or "dark";\n }\n\n # Render\n return (\n <div className="min-h-screen bg-background text-text-primary">\n <Header title="__NAME__" theme={theme} on_toggle_theme={handle_toggle_theme} />\n <main className="max-w-2xl mx-auto px-4 py-8">\n <Counter />\n </main>\n </div>\n );\n}\n';
124
+ glob _FRONTEND_APP = 'import "..styles.global.css";\nimport from .Header { Header }\nimport from .Counter { Counter }\n\ndef:pub Layout() -> JsxElement {\n # State\n has theme: str = "light";\n\n # Effects\n can with (theme) entry {\n if theme == "dark" {\n document.documentElement.classList.add("dark");\n } else {\n document.documentElement.classList.remove("dark");\n }\n }\n\n # Handlers\n def handle_toggle_theme() -> None {\n theme = (theme == "dark") and "light" or "dark";\n }\n\n # Render\n return (\n <div className="min-h-screen bg-background text-text-primary">\n <Header title="__NAME__" theme={theme} onToggleTheme={handle_toggle_theme} />\n <main className="max-w-2xl mx-auto px-4 py-8">\n <Counter />\n </main>\n </div>\n );\n}\n';
125
125
 
126
126
 
127
127
  # ===========================================================================
@@ -132,14 +132,14 @@ glob _FULLSTACK_MAIN = 'import from datetime { datetime }\n\n\nnode Item {\n
132
132
 
133
133
  glob _FULLSTACK_HOOK = 'sv import from ..main { get_items, add_item, delete_item }\n\ndef:pub useItems() -> dict {\n # State\n has items: list = [];\n has loading: bool = True;\n has error: str = "";\n\n # Fetch data on mount — returns typed list[Item] objects\n async can with entry {\n try {\n items = await get_items() or [];\n } except Exception as e {\n error = str(e);\n }\n loading = False;\n }\n\n # Handlers\n async def handle_add(name: str, description: str = "") -> None {\n if not name { return; }\n try {\n item = await add_item(name, description); # positional args only\n items = items + [item];\n } except Exception as e {\n error = str(e);\n }\n }\n\n async def handle_delete(item_id: str) -> None {\n try {\n await delete_item(item_id); # positional args only\n items = [i for i in items if jid(i) != item_id];\n } except Exception as e {\n error = str(e);\n }\n }\n\n return {\n "items": items,\n "loading": loading,\n "error": error,\n "handleAdd": handle_add,\n "handleDelete": handle_delete\n };\n}\n';
134
134
 
135
- glob _FULLSTACK_HEADER = 'import from ..lib.utils { cn }\n\ndef:pub Header(title: str, theme: str, on_toggle_theme: any) -> JsxElement {\n return (\n <header className="border-b border-border px-6 py-4 flex items-center justify-between">\n <h1 className="text-xl font-bold">{title}</h1>\n <button onClick={on_toggle_theme}\n className="px-3 py-1 bg-secondary text-secondary-foreground rounded-lg text-sm">\n {(theme == "dark") and "Light" or "Dark"}\n </button>\n </header>\n );\n}\n';
135
+ glob _FULLSTACK_HEADER = 'import from ..lib.utils { cn }\n\ndef:pub Header(props: dict) -> JsxElement {\n # Props — extract from dict\n title = props["title"] or "";\n theme = props["theme"] or "light";\n on_toggle_theme = props["onToggleTheme"] or None;\n\n return (\n <header className="border-b border-border px-6 py-4 flex items-center justify-between">\n <h1 className="text-xl font-bold">{title}</h1>\n <button onClick={on_toggle_theme}\n className="px-3 py-1 bg-secondary text-secondary-foreground rounded-lg text-sm">\n {(theme == "dark") and "Light" or "Dark"}\n </button>\n </header>\n );\n}\n';
136
136
 
137
137
  glob _FULLSTACK_ITEMLIST = 'import from ..lib.utils { cn }\nimport from ..hooks.useItems { useItems }\nimport from .ItemCard { ItemCard }\n\ndef:pub ItemList() -> JsxElement {\n # Fetch data — typed Item objects\n data = useItems();\n items = data["items"] or [];\n\n # State\n has input_value: str = "";\n\n # Handlers\n def handle_input_change(e: any) -> None {\n input_value = e.target.value;\n }\n\n def handle_add() -> None {\n if input_value {\n data["handleAdd"](input_value);\n input_value = "";\n }\n }\n\n def handle_key_down(e: any) -> None {\n if e.key == "Enter" {\n e.preventDefault();\n handle_add();\n }\n }\n\n # Guard\n if data["loading"] {\n return <p className="text-text-secondary text-center py-8">Loading...</p>;\n }\n\n # Render\n return (\n <div>\n {data["error"] and (\n <p className="text-error mb-4">{data["error"]}</p>\n )}\n <div className="flex gap-2 mb-6">\n <input\n value={input_value}\n onChange={handle_input_change}\n onKeyDown={handle_key_down}\n placeholder="Add an item..."\n className="flex-1 px-4 py-2 border border-border rounded-lg bg-surface"\n />\n <button onClick={handle_add}\n className="px-4 py-2 bg-primary text-primary-foreground rounded-lg flex items-center gap-1">\n + Add\n </button>\n </div>\n {len(items) == 0 and (\n <p className="text-text-secondary text-center py-8">No items yet. Add one above!</p>\n )}\n <div className="space-y-2">\n {[\n <ItemCard key={jid(item)} itemId={jid(item)} name={item.name} description={item.description} onDelete={data["handleDelete"]} />\n for item in items\n ]}\n </div>\n </div>\n );\n}\n';
138
138
 
139
- glob _FULLSTACK_APP = 'import "..styles.global.css";\nimport from .Header { Header }\nimport from .ItemList { ItemList }\n\ndef:pub Layout() -> JsxElement {\n # State\n has theme: str = "light";\n\n # Effects\n can with (theme) entry {\n if theme == "dark" {\n document.documentElement.classList.add("dark");\n } else {\n document.documentElement.classList.remove("dark");\n }\n }\n\n # Handlers\n def handle_toggle_theme() -> None {\n theme = (theme == "dark") and "light" or "dark";\n }\n\n # Render\n return (\n <div className="min-h-screen bg-background text-text-primary">\n <Header title="__NAME__" theme={theme} on_toggle_theme={handle_toggle_theme} />\n <main className="max-w-2xl mx-auto px-4 py-8">\n <ItemList />\n </main>\n </div>\n );\n}\n';
139
+ glob _FULLSTACK_APP = 'import "..styles.global.css";\nimport from .Header { Header }\nimport from .ItemList { ItemList }\n\ndef:pub Layout() -> JsxElement {\n # State\n has theme: str = "light";\n\n # Effects\n can with (theme) entry {\n if theme == "dark" {\n document.documentElement.classList.add("dark");\n } else {\n document.documentElement.classList.remove("dark");\n }\n }\n\n # Handlers\n def handle_toggle_theme() -> None {\n theme = (theme == "dark") and "light" or "dark";\n }\n\n # Render\n return (\n <div className="min-h-screen bg-background text-text-primary">\n <Header title="__NAME__" theme={theme} onToggleTheme={handle_toggle_theme} />\n <main className="max-w-2xl mx-auto px-4 py-8">\n <ItemList />\n </main>\n </div>\n );\n}\n';
140
140
 
141
141
 
142
- glob _FULLSTACK_ITEMCARD = 'def:pub ItemCard(props: dict) -> JsxElement {\n # Props — extract from dict\n itemId = props.itemId or "";\n name = props.name or "";\n description = props.description or "";\n on_delete = props.onDelete or None;\n\n # Handlers\n def handle_delete() -> None {\n if on_delete { on_delete(itemId); }\n }\n\n # Render\n return (\n <div className="flex items-center justify-between p-3 bg-surface border border-border rounded-lg">\n <div>\n <span className="font-medium">{name}</span>\n {description and (\n <p className="text-sm text-text-secondary mt-1">{description}</p>\n )}\n </div>\n <button onClick={handle_delete}\n className="text-error hover:opacity-75">\n ×\n </button>\n </div>\n );\n}\n';
142
+ glob _FULLSTACK_ITEMCARD = 'def:pub ItemCard(props: dict) -> JsxElement {\n # Props — extract from dict\n itemId = props["itemId"] or "";\n name = props["name"] or "";\n description = props["description"] or "";\n on_delete = props["onDelete"] or None;\n\n # Handlers\n def handle_delete() -> None {\n if on_delete { on_delete(itemId); }\n }\n\n # Render\n return (\n <div className="flex items-center justify-between p-3 bg-surface border border-border rounded-lg">\n <div>\n <span className="font-medium">{name}</span>\n {description and (\n <p className="text-sm text-text-secondary mt-1">{description}</p>\n )}\n </div>\n <button onClick={handle_delete}\n className="text-error hover:opacity-75">\n ×\n </button>\n </div>\n );\n}\n';
143
143
 
144
144
 
145
145
  # ===========================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jac-coder
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: AI coding agent backend for Jac, powered by jac-byllm
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: python-dotenv>=1.0.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jac-coder"
7
- version = "0.1.4"
7
+ version = "0.1.5"
8
8
  description = "AI coding agent backend for Jac, powered by jac-byllm"
9
9
  requires-python = ">=3.12"
10
10
  dependencies = [
File without changes