jac-coder 0.1.3__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.
- {jac_coder-0.1.3 → jac_coder-0.1.5}/PKG-INFO +1 -1
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-312/api.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-312/config.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/context.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-312/cost_tracker.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/nodes.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/scaffold.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-313/api.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-313/config.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/context.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-313/cost_tracker.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/nodes.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/scaffold.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-314/api.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-314/config.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/context.jir +0 -0
- jac_coder-0.1.5/jac_coder/_precompiled/cpython-314/cost_tracker.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/nodes.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/scaffold.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/manifest.json +7 -7
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/api.jac +2 -1
- jac_coder-0.1.5/jac_coder/config.jac +88 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/examples/blog_app.md +6 -7
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/reference/frontend.md +12 -8
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/reference/pitfalls.md +4 -4
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/rules/fullstack.md +16 -10
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/api.impl.jac +26 -1
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/context.impl.jac +1 -1
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/cost_tracker.impl.jac +16 -11
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/nodes.impl.jac +3 -2
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/scaffold.impl.jac +5 -5
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder.egg-info/PKG-INFO +1 -1
- {jac_coder-0.1.3 → jac_coder-0.1.5}/pyproject.toml +1 -1
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-312/api.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-312/config.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-312/cost_tracker.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-313/api.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-313/config.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-313/cost_tracker.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-314/api.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-314/config.jir +0 -0
- jac_coder-0.1.3/jac_coder/_precompiled/cpython-314/cost_tracker.jir +0 -0
- jac_coder-0.1.3/jac_coder/config.jac +0 -40
- {jac_coder-0.1.3 → jac_coder-0.1.5}/README.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/__init__.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/__init__.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/events.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/mcp_manager.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/memory.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/permission.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/prompt.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/serve_entry.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/server.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/checked.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/delegation.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/filesystem.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/git.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/guarded.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/jac_analyzer.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/jac_docs.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/jac_tools.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/mcp.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/preview.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/question.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/search.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/shell.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/task.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/think.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/todo.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/validate.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/tool/web.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/colors.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/sandbox.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/util/tool_output.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-312/walkers.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/events.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/mcp_manager.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/memory.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/permission.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/prompt.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/serve_entry.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/server.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/checked.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/delegation.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/filesystem.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/git.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/guarded.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/jac_analyzer.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/jac_docs.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/jac_tools.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/mcp.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/preview.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/question.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/search.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/shell.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/task.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/think.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/todo.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/validate.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/tool/web.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/colors.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/sandbox.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/util/tool_output.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-313/walkers.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/events.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/mcp_manager.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/memory.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/permission.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/prompt.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/serve_entry.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/server.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/checked.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/delegation.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/filesystem.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/git.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/guarded.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/jac_analyzer.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/jac_docs.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/jac_tools.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/mcp.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/preview.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/question.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/search.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/shell.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/task.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/think.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/todo.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/validate.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/tool/web.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/__init__.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/colors.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/sandbox.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/util/tool_output.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/_precompiled/cpython-314/walkers.jir +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/cli_entry.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/context.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/cost_tracker.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/examples/ai_agent.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/examples/core_patterns.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/examples/todo_app.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/reference/ai.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/reference/backend.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/reference/osp.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/reference/syntax.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/rules/core_jac.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/data/rules/workflow.md +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/events.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/config.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/mcp_manager.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/memory.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/permission.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/prompt.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/impl/walkers.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/mcp_manager.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/memory.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/nodes.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/permission.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/prompt.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/serve_entry.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/server.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/__init__.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/checked.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/delegation.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/filesystem.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/git.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/guarded.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/checked.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/delegation.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/filesystem.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/git.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/guarded.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/jac_analyzer.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/jac_docs.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/jac_tools.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/mcp.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/preview.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/question.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/search.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/shell.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/task.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/think.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/todo.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/validate.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/impl/web.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/jac_analyzer.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/jac_docs.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/jac_tools.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/mcp.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/preview.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/question.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/scaffold.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/search.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/shell.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/task.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/think.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/todo.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/validate.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/tool/web.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/util/__init__.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/util/colors.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/util/impl/sandbox.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/util/impl/tool_output.impl.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/util/sandbox.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/util/tool_output.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder/walkers.jac +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder.egg-info/SOURCES.txt +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder.egg-info/dependency_links.txt +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder.egg-info/entry_points.txt +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder.egg-info/requires.txt +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/jac_coder.egg-info/top_level.txt +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/setup.cfg +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/tests/test_context.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/tests/test_events.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/tests/test_graph.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/tests/test_interact.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/tests/test_memory.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/tests/test_selfcorrect.py +0 -0
- {jac_coder-0.1.3 → jac_coder-0.1.5}/tests/test_tools.py +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -5,25 +5,25 @@
|
|
|
5
5
|
},
|
|
6
6
|
"api.jac": {
|
|
7
7
|
"impl_hashes": {
|
|
8
|
-
"impl/api.impl.jac": "
|
|
8
|
+
"impl/api.impl.jac": "20d793ad7cc3a21ec126872d6665a56af6b244182dc04f151e771f06f2fbc1c0"
|
|
9
9
|
},
|
|
10
|
-
"source_hash": "
|
|
10
|
+
"source_hash": "6fd2526d7eaf26c7b0cd95877381945a45734a75845b67fa4245d781db4a04b9"
|
|
11
11
|
},
|
|
12
12
|
"config.jac": {
|
|
13
13
|
"impl_hashes": {
|
|
14
14
|
"impl/config.impl.jac": "2765b4930f5bc7ff4453d4203c072f1dccb131b53fd76c64ad2c7f769b891663"
|
|
15
15
|
},
|
|
16
|
-
"source_hash": "
|
|
16
|
+
"source_hash": "1c804b1d5e46039cca3ef67dc890c6a8dee6a3cdfd561ea181f1b9c56719b3e5"
|
|
17
17
|
},
|
|
18
18
|
"context.jac": {
|
|
19
19
|
"impl_hashes": {
|
|
20
|
-
"impl/context.impl.jac": "
|
|
20
|
+
"impl/context.impl.jac": "03c0645bf220dec2bc43438557229b8783f72be4ca46b48525ff767e1846559d"
|
|
21
21
|
},
|
|
22
22
|
"source_hash": "b4602e99adfc979830b189346050d205dcce45ba4a58f43bd3e5e0dc52dc84bd"
|
|
23
23
|
},
|
|
24
24
|
"cost_tracker.jac": {
|
|
25
25
|
"impl_hashes": {
|
|
26
|
-
"impl/cost_tracker.impl.jac": "
|
|
26
|
+
"impl/cost_tracker.impl.jac": "f6fc36660b31917b93f3a73b44aaaa340e024e45b9a855dbfc9e35f713a52032"
|
|
27
27
|
},
|
|
28
28
|
"source_hash": "41f2358725b03d093102da10138b9334e04e36d600b1fff1e13566b434c70179"
|
|
29
29
|
},
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"nodes.jac": {
|
|
46
46
|
"impl_hashes": {
|
|
47
|
-
"impl/nodes.impl.jac": "
|
|
47
|
+
"impl/nodes.impl.jac": "224d675e46ae4a54afac2ac47db5c66dc11ece25af4085d2eebe8fc7e33b75f8"
|
|
48
48
|
},
|
|
49
49
|
"source_hash": "eae8bd478013a0d330ce40b2c321cfa53fe9e664bbc8ae6d03d6010c61f339ac"
|
|
50
50
|
},
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
},
|
|
138
138
|
"tool/scaffold.jac": {
|
|
139
139
|
"impl_hashes": {
|
|
140
|
-
"tool/impl/scaffold.impl.jac": "
|
|
140
|
+
"tool/impl/scaffold.impl.jac": "1e465d3a37c2f63638a12876d490cd9384a47479152a85fc8373a12bf0b8505a"
|
|
141
141
|
},
|
|
142
142
|
"source_hash": "ebb6d09098f1941aa4baf9f54541bef6a0e430b32549feda0d4021448e4a12d8"
|
|
143
143
|
},
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import os;
|
|
2
|
+
import json;
|
|
3
|
+
import threading;
|
|
4
|
+
import from pathlib { Path }
|
|
5
|
+
import from dotenv { load_dotenv }
|
|
6
|
+
import from byllm.lib { Model }
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
obj JacCoderConfig {
|
|
10
|
+
has default_model: str = "gpt-5.2-2025-12-11",
|
|
11
|
+
temperature: float = 0.2,
|
|
12
|
+
max_tokens: int = 16384,
|
|
13
|
+
max_react_iterations: int = 30,
|
|
14
|
+
project_dir: str = "";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
glob _config: JacCoderConfig = JacCoderConfig();
|
|
18
|
+
glob model_name: str = _config.default_model;
|
|
19
|
+
|
|
20
|
+
# Thread-safe per-session model override.
|
|
21
|
+
# SessionAwareModel overrides invoke() to check thread-local state.
|
|
22
|
+
# `by llm()` calls llm.invoke(mt_run) → our override creates a
|
|
23
|
+
# per-call Model with the thread's model_name/api_key if set.
|
|
24
|
+
# No global mutation, no cross-thread contamination.
|
|
25
|
+
import from jaclang.jac0core.runtime { MTRuntime }
|
|
26
|
+
|
|
27
|
+
glob _tl = threading.local();
|
|
28
|
+
|
|
29
|
+
obj SessionAwareModel(Model) {
|
|
30
|
+
override def invoke(mt_run: MTRuntime) -> object {
|
|
31
|
+
import logging;
|
|
32
|
+
_logger = logging.getLogger("jac_coder.config");
|
|
33
|
+
tl_model = getattr(_tl, "model_name", "");
|
|
34
|
+
_logger.info(f"SessionAwareModel.invoke() tl_model={tl_model} default={self.model_name}");
|
|
35
|
+
if tl_model {
|
|
36
|
+
tl_key = getattr(_tl, "api_key", "");
|
|
37
|
+
temp = Model(model_name=tl_model, api_key=tl_key) if tl_key else Model(model_name=tl_model);
|
|
38
|
+
_logger.info(f"Delegating to temp Model: {tl_model} has_key={bool(tl_key)}");
|
|
39
|
+
return temp.invoke(mt_run);
|
|
40
|
+
}
|
|
41
|
+
return super.invoke(mt_run);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
glob llm = SessionAwareModel(model_name=model_name);
|
|
46
|
+
|
|
47
|
+
"""Set a thread-local model override. Fully concurrent — no locks, no global mutation."""
|
|
48
|
+
def set_session_llm(model_name_override: str, api_key_override: str = "") {
|
|
49
|
+
import logging;
|
|
50
|
+
_tl.model_name = model_name_override;
|
|
51
|
+
_tl.api_key = api_key_override;
|
|
52
|
+
logging.getLogger("jac_coder.config").info(
|
|
53
|
+
f"Session LLM set: thread={threading.current_thread().name} model={model_name_override} has_key={bool(api_key_override)}"
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
"""Clear the thread-local model override."""
|
|
58
|
+
def clear_session_llm() {
|
|
59
|
+
import logging;
|
|
60
|
+
prev = getattr(_tl, "model_name", "");
|
|
61
|
+
_tl.model_name = "";
|
|
62
|
+
_tl.api_key = "";
|
|
63
|
+
if prev {
|
|
64
|
+
logging.getLogger("jac_coder.config").info(
|
|
65
|
+
f"Session LLM cleared: thread={threading.current_thread().name} was={prev}"
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# --- Config ---
|
|
71
|
+
def _merge_from_file(config: JacCoderConfig, path: str) -> None;
|
|
72
|
+
def load_config(project_dir: str = "") -> JacCoderConfig;
|
|
73
|
+
def get_config() -> JacCoderConfig;
|
|
74
|
+
def get_home_dir() -> str;
|
|
75
|
+
def get_data_dir() -> str;
|
|
76
|
+
|
|
77
|
+
# --- Model management ---
|
|
78
|
+
def set_model(model: str) -> dict;
|
|
79
|
+
def get_model() -> dict;
|
|
80
|
+
|
|
81
|
+
with entry {
|
|
82
|
+
load_dotenv(override=True);
|
|
83
|
+
load_config();
|
|
84
|
+
# Sync the default LLM with loaded config — created at module load time
|
|
85
|
+
# with the hardcoded default before load_config() runs.
|
|
86
|
+
model_name = _config.default_model;
|
|
87
|
+
llm.model_name = model_name;
|
|
88
|
+
}
|
|
@@ -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
|
|
281
|
+
onDelete = props["onDelete"] or None;
|
|
283
282
|
|
|
284
283
|
# Props are always dict — extract values
|
|
285
|
-
postId = props
|
|
286
|
-
title = props
|
|
287
|
-
body = props
|
|
288
|
-
category = props
|
|
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
|
|
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
|
|
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={
|
|
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
|
|
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
|
|
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
|
|
145
|
-
completed = props
|
|
146
|
-
todoId = props
|
|
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
|
|
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
|
|
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
|
|
61
|
-
title = props
|
|
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
|
|
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
|
|
161
|
-
theme = props
|
|
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 —
|
|
229
|
+
## Event handlers — ALWAYS use named functions
|
|
230
230
|
|
|
231
231
|
```jac
|
|
232
|
-
#
|
|
232
|
+
# RIGHT — named function ABOVE return, passed by name
|
|
233
233
|
def handle_click() -> None {
|
|
234
234
|
count = count + 1;
|
|
235
235
|
}
|
|
236
|
-
|
|
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
|
-
#
|
|
244
|
+
# WRONG — lambda in JSX
|
|
239
245
|
<input onChange={lambda e: any -> None { text = e.target.value; }} />
|
|
240
246
|
|
|
241
|
-
# WRONG — inline def
|
|
247
|
+
# WRONG — inline def in JSX
|
|
242
248
|
<button onClick={def(e: any) -> None { count = count + 1; }}>
|
|
243
249
|
```
|
|
244
250
|
|
|
245
|
-
|
|
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
|
|
382
|
-
title = props
|
|
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`.
|
|
@@ -131,7 +131,8 @@ impl chat(
|
|
|
131
131
|
mode: str = "full",
|
|
132
132
|
agent_context: str = "",
|
|
133
133
|
images: list = [],
|
|
134
|
-
edit_mode: str = "auto"
|
|
134
|
+
edit_mode: str = "auto",
|
|
135
|
+
env_overrides: dict = {}
|
|
135
136
|
) -> dict {
|
|
136
137
|
# Find session — try registry first (works across threads), then graph
|
|
137
138
|
session = _session_registry.get(session_id);
|
|
@@ -152,6 +153,25 @@ impl chat(
|
|
|
152
153
|
}
|
|
153
154
|
work_dir = session.directory;
|
|
154
155
|
|
|
156
|
+
# Apply per-session env overrides (e.g. user's OPENAI_API_KEY from IDE settings).
|
|
157
|
+
# Stores a thread-local Model override so the user's key is used for this
|
|
158
|
+
# session only — no mutation of os.environ or the global llm object.
|
|
159
|
+
_has_llm_override = False;
|
|
160
|
+
if env_overrides {
|
|
161
|
+
import from jac_coder.config { set_session_llm }
|
|
162
|
+
import logging as _chatlog;
|
|
163
|
+
_api_key = str(env_overrides.get("OPENAI_API_KEY", env_overrides.get("ANTHROPIC_API_KEY", "")));
|
|
164
|
+
_model_name = str(env_overrides.get("MODEL", ""));
|
|
165
|
+
_chatlog.getLogger("jac_coder.api").info(f"env_overrides received: model={_model_name} has_key={bool(_api_key)}");
|
|
166
|
+
if _api_key or _model_name {
|
|
167
|
+
import from jac_coder.config { llm as _current_llm }
|
|
168
|
+
_override_model_name = _model_name or str(_current_llm.model_name);
|
|
169
|
+
_chatlog.getLogger("jac_coder.api").info(f"Applying session override: {_current_llm.model_name} -> {_override_model_name}");
|
|
170
|
+
set_session_llm(_override_model_name, _api_key);
|
|
171
|
+
_has_llm_override = True;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
155
175
|
# Bind session_id + edit_mode to this thread so guarded tools know
|
|
156
176
|
# whether to auto-allow, prompt, or deny write/edit/bash operations.
|
|
157
177
|
_set_chat_session(session_id, edit_mode);
|
|
@@ -342,6 +362,11 @@ impl chat(
|
|
|
342
362
|
if on_event {
|
|
343
363
|
clear_event_callbacks();
|
|
344
364
|
}
|
|
365
|
+
# Clear thread-local LLM override
|
|
366
|
+
if _has_llm_override {
|
|
367
|
+
import from jac_coder.config { clear_session_llm }
|
|
368
|
+
clear_session_llm();
|
|
369
|
+
}
|
|
345
370
|
# Clean up thread context (session_id + edit_mode)
|
|
346
371
|
_clear_chat_session();
|
|
347
372
|
}
|
|
@@ -14,7 +14,7 @@ def _build_prefix(
|
|
|
14
14
|
# This is the agent's persistent knowledge of the project state.
|
|
15
15
|
is_progress_file = project_summary.lstrip().startswith("#");
|
|
16
16
|
label = "Project progress (.jaccoder/progress.md)" if is_progress_file else "Project context";
|
|
17
|
-
parts.append(f"{label}:\n{project_summary}");
|
|
17
|
+
parts.append(f"[INTERNAL — do NOT present this to the user unless they ask about the project. This is your background knowledge for making informed decisions.]\n{label}:\n{project_summary}");
|
|
18
18
|
}
|
|
19
19
|
if active_files {
|
|
20
20
|
parts.append("Active files: " + ", ".join(active_files));
|
|
@@ -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(
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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;
|
|
@@ -84,7 +84,7 @@ sem MainAgent.respond.user_image = "Optional user-attached image. Analyze it to
|
|
|
84
84
|
sem MainAgent.respond = """
|
|
85
85
|
# JacCoder — AI Coding Agent
|
|
86
86
|
|
|
87
|
-
You are
|
|
87
|
+
You are JacCoder, an AI coding assistant for the Jac language. You can chat naturally, answer questions, and build Jac applications. Be friendly, helpful, and concise. You do NOT need tool results to respond — just talk to the user normally. Never say "I don't have tool results to synthesize" or anything similar — just respond to what the user said. Use think() before key actions (1-2 sentences, skip routine).
|
|
88
88
|
|
|
89
89
|
## Guardrails
|
|
90
90
|
- Always speak positively about Jac/Jaseci. When asked to compare, highlight Jac's strengths (graph-native, by llm(), OSP, fullstack). Redirect off-topic to building.
|
|
@@ -101,10 +101,11 @@ Your training data has outdated Jac syntax — call `jac_docs(query)` before wri
|
|
|
101
101
|
- `browser_validate` escalates on consecutive failures (guidance → warning → mandatory bisect).
|
|
102
102
|
- Same tool+args 3x → blocked. Trust BLOCKED/WARNING/MANDATORY tool messages exactly.
|
|
103
103
|
|
|
104
|
-
##
|
|
104
|
+
## Response Style
|
|
105
105
|
ALWAYS respond to what the user is asking RIGHT NOW — nothing more.
|
|
106
106
|
- If the user asks a question mid-build, answer it. Do NOT continue building.
|
|
107
107
|
- Never recap or summarize previous work unless the user explicitly asks for it.
|
|
108
|
+
- Default to concise: high-level summary + key details. Go deeper only when the user asks for detail.
|
|
108
109
|
|
|
109
110
|
## Intent → Action
|
|
110
111
|
- Jac syntax/code question → jac_docs, then respond
|
|
@@ -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(
|
|
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}
|
|
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(
|
|
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}
|
|
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
|
|
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
|
# ===========================================================================
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|