kon-coding-agent 0.3.3__tar.gz → 0.3.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 (139) hide show
  1. kon_coding_agent-0.3.5/.github/workflows/test.yml +33 -0
  2. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/.kon/skills/kon-release-publish/SKILL.md +16 -9
  3. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/AGENTS.md +1 -0
  4. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/CHANGELOG.md +64 -0
  5. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/PKG-INFO +1 -1
  6. kon_coding_agent-0.3.5/docs/local-models.md +80 -0
  7. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/pyproject.toml +1 -1
  8. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/config.py +1 -0
  9. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/defaults/config.toml +3 -0
  10. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/base.py +1 -1
  11. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/openai_completions.py +31 -10
  12. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/openai_responses.py +3 -0
  13. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/session.py +148 -17
  14. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/edit.py +1 -1
  15. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/app.py +22 -21
  16. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/chat.py +17 -2
  17. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/commands.py +26 -72
  18. kon_coding_agent-0.3.5/src/kon/ui/export.py +693 -0
  19. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/floating_list.py +70 -8
  20. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/session_ui.py +14 -52
  21. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/widgets.py +116 -42
  22. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/context/test_skills.py +1 -1
  23. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_handoff.py +4 -6
  24. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_launch_warnings.py +1 -1
  25. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_openai_compat.py +108 -1
  26. kon_coding_agent-0.3.5/tests/test_session_queries.py +61 -0
  27. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_session_resume.py +1 -5
  28. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_edit_display.py +2 -2
  29. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/uv.lock +1 -1
  30. kon_coding_agent-0.3.3/docs/local-models.md +0 -42
  31. kon_coding_agent-0.3.3/src/kon/ui/export.py +0 -330
  32. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/.gitignore +0 -0
  33. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/.kon/skills/kon-tmux-test/SKILL.md +0 -0
  34. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/.kon/skills/kon-tmux-test/run-e2e-tests.sh +0 -0
  35. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/.kon/skills/kon-tmux-test/setup-test-project.sh +0 -0
  36. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/.python-version +0 -0
  37. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/LICENSE +0 -0
  38. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/README.md +0 -0
  39. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/docs/architecture-review.md +0 -0
  40. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/docs/images/kon-screenshot.png +0 -0
  41. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/scripts/show_themes.py +0 -0
  42. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/__init__.py +0 -0
  43. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/async_utils.py +0 -0
  44. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/builtin_skills/init/SKILL.md +0 -0
  45. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/context/__init__.py +0 -0
  46. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/context/_xml.py +0 -0
  47. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/context/agent_mds.py +0 -0
  48. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/context/git.py +0 -0
  49. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/context/loader.py +0 -0
  50. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/context/skills.py +0 -0
  51. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/core/__init__.py +0 -0
  52. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/core/compaction.py +0 -0
  53. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/core/handoff.py +0 -0
  54. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/core/types.py +0 -0
  55. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/defaults/__init__.py +0 -0
  56. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/events.py +0 -0
  57. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/__init__.py +0 -0
  58. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/models.py +0 -0
  59. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/oauth/__init__.py +0 -0
  60. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/oauth/copilot.py +0 -0
  61. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/oauth/openai.py +0 -0
  62. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/__init__.py +0 -0
  63. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/anthropic.py +0 -0
  64. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/azure_ai_foundry.py +0 -0
  65. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/copilot.py +0 -0
  66. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/copilot_anthropic.py +0 -0
  67. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/github_copilot_headers.py +0 -0
  68. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/mock.py +0 -0
  69. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/openai_codex_responses.py +0 -0
  70. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/openai_compat.py +0 -0
  71. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/llm/providers/sanitize.py +0 -0
  72. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/loop.py +0 -0
  73. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/permissions.py +0 -0
  74. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/py.typed +0 -0
  75. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/themes.py +0 -0
  76. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/__init__.py +0 -0
  77. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/_read_image.py +0 -0
  78. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/_tool_utils.py +0 -0
  79. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/base.py +0 -0
  80. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/bash.py +0 -0
  81. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/find.py +0 -0
  82. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/grep.py +0 -0
  83. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/read.py +0 -0
  84. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/web_fetch.py +0 -0
  85. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/web_search.py +0 -0
  86. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools/write.py +0 -0
  87. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/tools_manager.py +0 -0
  88. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/turn.py +0 -0
  89. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/__init__.py +0 -0
  90. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/app_protocol.py +0 -0
  91. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/autocomplete.py +0 -0
  92. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/blocks.py +0 -0
  93. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/clipboard.py +0 -0
  94. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/formatting.py +0 -0
  95. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/input.py +0 -0
  96. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/path_complete.py +0 -0
  97. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/prompt_history.py +0 -0
  98. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/selection_mode.py +0 -0
  99. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/ui/styles.py +0 -0
  100. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/src/kon/update_check.py +0 -0
  101. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/conftest.py +0 -0
  102. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/context/test_agents.py +0 -0
  103. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/llm/__init__.py +0 -0
  104. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/llm/test_anthropic_provider.py +0 -0
  105. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/llm/test_azure_ai_foundry_provider.py +0 -0
  106. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/llm/test_mock_provider.py +0 -0
  107. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/llm/test_openai_codex_provider_errors.py +0 -0
  108. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/llm/test_openai_oauth.py +0 -0
  109. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_agentic_loop.py +0 -0
  110. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_cli_auth_flags.py +0 -0
  111. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_cli_provider_resolution.py +0 -0
  112. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_compaction.py +0 -0
  113. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_config_binaries.py +0 -0
  114. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_config_error_fallback.py +0 -0
  115. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_config_injection.py +0 -0
  116. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_config_migration.py +0 -0
  117. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_handoff_link_interrupt.py +0 -0
  118. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_local_auth_config.py +0 -0
  119. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_model_provider_resolution.py +0 -0
  120. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_permissions.py +0 -0
  121. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_session_persistence.py +0 -0
  122. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_system_prompt.py +0 -0
  123. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_system_prompt_git_context.py +0 -0
  124. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_tools_manager.py +0 -0
  125. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_update_check.py +0 -0
  126. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/test_update_notice_behavior.py +0 -0
  127. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_diff.py +0 -0
  128. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_edit.py +0 -0
  129. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_read.py +0 -0
  130. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_read_image.py +0 -0
  131. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_read_image_integration.py +0 -0
  132. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_subprocess_cancellation.py +0 -0
  133. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/tools/test_write.py +0 -0
  134. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/ui/test_autocomplete.py +0 -0
  135. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/ui/test_floating_list.py +0 -0
  136. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/ui/test_input_handoff.py +0 -0
  137. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/ui/test_input_paste.py +0 -0
  138. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/ui/test_prompt_history.py +0 -0
  139. {kon_coding_agent-0.3.3 → kon_coding_agent-0.3.5}/tests/ui/test_status_line.py +0 -0
@@ -0,0 +1,33 @@
1
+ name: Test
2
+
3
+ on: [push, pull_request]
4
+
5
+ permissions:
6
+ contents: read
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.12","3.13", "3.14"]
14
+ steps:
15
+ - uses: actions/checkout@v3
16
+ - name: Set up Python ${{ matrix.python-version }}
17
+ uses: actions/setup-python@v4
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ cache: pip
21
+ cache-dependency-path: pyproject.toml
22
+ - name: Cache models
23
+ uses: actions/cache@v3
24
+ with:
25
+ path: ~/.cache
26
+ key: ${{ runner.os }}-torch-
27
+ - name: Install dependencies
28
+ run: |
29
+ pip install . --group dev
30
+ - name: Run tests
31
+ run: |
32
+ python -m pytest -s
33
+
@@ -33,38 +33,44 @@ Use this skill when the user asks to cut a new Kon version, tag it, publish to P
33
33
  - `git status --short --branch` must be clean (or confirm with user)
34
34
  - `git tag --list` and `git log --oneline <prev_tag>..HEAD` to summarize changes
35
35
 
36
- 2. **Version bump**
36
+ 2. **Update CHANGELOG.md**
37
+ - Replace the `## [Unreleased]` section's `- No changes yet.` with a new versioned heading: `## <version> - YYYY-MM-DD`
38
+ - Use `git log --oneline <prev_tag>..HEAD` to categorize changes into `### Added`, `### Changed`, `### Fixed` sections
39
+ - Credit external contributors with `- @username`
40
+ - Commit message: `docs: update changelog for <version>`
41
+
42
+ 3. **Version bump**
37
43
  - Update version in all 3 files above
38
44
 
39
- 3. **Quality gates**
45
+ 4. **Quality gates**
40
46
  - `uv run ruff format .`
41
47
  - `uv run ruff check .`
42
48
  - `uv run pyright .`
43
49
  - `uv run pytest`
44
50
 
45
- 4. **Commit**
51
+ 5. **Commit**
46
52
  - Commit message: `build: bump version to <version>`
47
53
 
48
- 5. **Tag**
54
+ 6. **Tag**
49
55
  - Annotated tag: `git tag -a v<version> -m "v<version> ..."`
50
- - Include concise changes since previous tag bullets
56
+ - Include concise "changes since previous tag" bullets
51
57
 
52
- 6. **Push**
58
+ 7. **Push**
53
59
  - `git push origin main`
54
60
  - `git push origin v<version>`
55
61
 
56
- 7. **Build + verify artifacts**
62
+ 8. **Build + verify artifacts**
57
63
  - `rm -rf dist && uv build`
58
64
  - `uv run python -m twine check dist/*`
59
65
 
60
- 8. **Publish to PyPI**
66
+ 9. **Publish to PyPI**
61
67
  - Prefer token file if present (example `~/.pypi-token`):
62
68
  - `TWINE_USERNAME=__token__ TWINE_PASSWORD="$(< ~/.pypi-token)" uv run python -m twine upload dist/*`
63
69
  - Verify:
64
70
  - `https://pypi.org/project/kon-coding-agent/<version>/`
65
71
  - `https://pypi.org/pypi/kon-coding-agent/json` reports latest version
66
72
 
67
- 9. **Create GitHub release**
73
+ 10. **Create GitHub release**
68
74
  - If token exists at `~/.github-token`, call Releases API:
69
75
  - `POST /repos/<owner>/<repo>/releases` with:
70
76
  - `tag_name: v<version>`
@@ -83,6 +89,7 @@ Use this skill when the user asks to cut a new Kon version, tag it, publish to P
83
89
 
84
90
  ## Output checklist to report
85
91
 
92
+ - Changelog updated for `<version>`
86
93
  - Version bumped in all files
87
94
  - Checks passed
88
95
  - Commit hash
@@ -4,6 +4,7 @@
4
4
 
5
5
  - Don't add trivial docstrings. Only add docstrings when explaining complex functionality.
6
6
  - This project uses `uv`. Run `uv run ruff format .` after editing or creating any files.
7
+ - If generating and running a Python script, use `uv run python` instead of `python`.
7
8
 
8
9
  ## Testing
9
10
 
@@ -6,6 +6,70 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  - No changes yet.
8
8
 
9
+ ## 0.3.5 - 2026-04-18
10
+
11
+ ### Added
12
+
13
+ - Standalone session HTML export with self-contained styling.
14
+ - Configurable request timeout for API calls - @jspruit.
15
+ - GitHub CI tests for Python 3.12–3.13 - @sukhbinder.
16
+ - Width-aware popup lists and queue display.
17
+
18
+ ### Changed
19
+
20
+ - Highlight color applied to the second column in floating lists.
21
+ - Batch scroll during streaming, cache query_one lookups, pause spinner timer when idle.
22
+ - Diff line length capped at 200 characters.
23
+
24
+ ### Fixed
25
+
26
+ - Persist thinking level in session header and change all defaults to high.
27
+ - Normalize OpenAI provider imports.
28
+ - Widen resume popup labels.
29
+ - Remove unused UI app import.
30
+
31
+ ### Performance
32
+
33
+ - Added `gc.freeze()` and `PAUSE_GC_ON_SCROLL` to reduce GC stutters.
34
+
35
+ ## 0.3.4 - 2026-04-10
36
+
37
+ ### Fixed
38
+
39
+ - Fixed Windows UTF-8 encoding errors in file operations - @sukhbinder.
40
+ - Fixed local Gemma model thinking block compatibility.
41
+ - Removed duplicate force-include for builtin skills in build config.
42
+
43
+ ### Changed
44
+
45
+ - Updated local model documentation.
46
+
47
+ ## 0.3.3 - 2026-04-08
48
+
49
+ ### Added
50
+
51
+ - Added queued agent steering between turns - @0xku.
52
+ - Added bundled `/init` slash command for project scaffolding - @0xku.
53
+ - Added help info for queue and steer queue commands.
54
+ - Added GLM-5.1 support for zai provider.
55
+
56
+ ### Changed
57
+
58
+ - Improved read tool directory listings.
59
+ - Updated README with steer queue documentation.
60
+ - Added `$` icon for bash, `%` for web tools, and `←` for edit tool.
61
+ - Used muted color for shortcut key hints in exit/delete prompts.
62
+
63
+ ### Fixed
64
+
65
+ - Let ESC interrupt retry backoff immediately - @0xku.
66
+ - Fixed OpenAI login stdin leak by removing orphaned thread - @Meltedd.
67
+ - Fixed OpenAI and Anthropic local compat with auth flags.
68
+ - Fixed interrupt handling before handoff thread switch.
69
+ - Fixed subprocess communication drain on cancellation/timeout.
70
+ - Added zipfile path traversal validation.
71
+ - Removed token throughput metrics.
72
+
9
73
  ## 0.3.2 - 2026-03-22
10
74
 
11
75
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kon-coding-agent
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Minimal coding agent
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -0,0 +1,80 @@
1
+ # Local Models
2
+
3
+ This document provides detailed information about running and configuring local models with Kon.
4
+
5
+ ## Tested Models
6
+
7
+ > Tested on llama server build b8740
8
+
9
+ | Model | Quantization | Context Length | TPS | System Specs |
10
+ | ----- | -------------- | -------------- | --- | ------------ |
11
+ | `zai-org/glm-4.7-flash` | Q4_K_M | 65,536 | N/A | i7-14700F × 28, 64GB RAM, 24GB VRAM (RTX 3090) |
12
+ | `unsloth/Qwen3.5-27B-GGUF` | Q4_K_M | 32,768 | ~30 | i7-14700F × 28, 64GB RAM, 24GB VRAM (RTX 3090) |
13
+ | `unsloth/gemma-4-26B-A4B-it-GGUF` | UD-Q4_K_M | 32,768 | ~100 | i7-14700F × 28, 64GB RAM, 24GB VRAM (RTX 3090) |
14
+
15
+ Run Qwen3.5 27B on an RTX 3090 with a 32k context window using llama-server:
16
+
17
+ ```bash
18
+ /path-to-llama-server/llama-server \
19
+ --model /path-to-model/Qwen3.5-27B-Q4_K_M.gguf \
20
+ --port 5000 \
21
+ --ctx-size 32768 \
22
+ --gpu-layers all \
23
+ --threads 8 \
24
+ --threads-batch 8 \
25
+ --batch-size 1024 \
26
+ --ubatch-size 512 \
27
+ --flash-attn on
28
+ ```
29
+
30
+ On this machine, that setup generates at roughly 30 tokens per second.
31
+
32
+ Then start Kon for a one-off local session:
33
+
34
+ ```bash
35
+ kon --model unsloth/Qwen3.5-27B-GGUF --provider openai \
36
+ --base-url http://localhost:5000/v1 \
37
+ --openai-compat-auth none
38
+ ```
39
+
40
+ Run Gemma 4 26B A4B on the same machine using llama-server:
41
+
42
+ ```bash
43
+ /path-to-llama-server/llama-server \
44
+ --model /path-to-model/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf \
45
+ --port 5000 \
46
+ --ctx-size 32768 \
47
+ --gpu-layers all \
48
+ --threads 8 \
49
+ --threads-batch 8 \
50
+ --batch-size 1024 \
51
+ --ubatch-size 512 \
52
+ --flash-attn on \
53
+ --temperature 1.5
54
+ ```
55
+
56
+ Then start Kon against that local server:
57
+
58
+ ```bash
59
+ kon --model unsloth/gemma-4-26B-A4B-it-GGUF --provider openai \
60
+ --base-url http://localhost:5000/v1 \
61
+ --openai-compat-auth none
62
+ ```
63
+
64
+ To avoid passing provider, model, and auth flags every time you start Kon, you can define your local setup in `~/.kon/config.toml`. This also allows you to tune compaction to trigger at a specific point relative to your model's context window.
65
+
66
+ If this is your default setup, put it in `~/.kon/config.toml` instead:
67
+
68
+ ```toml
69
+ [llm]
70
+ default_provider = "openai"
71
+ default_model = "unsloth/gemma-4-26B-A4B-it-GGUF"
72
+ default_base_url = "http://localhost:5000/v1"
73
+
74
+ [llm.auth]
75
+ openai_compat = "none" # or "auto"
76
+
77
+ [compaction]
78
+ # Set this close to your model's context size (e.g., 30000 for a 32k window)
79
+ buffer_tokens = 27768 # 32768 - 5000 (safety margin)
80
+ ```
@@ -14,7 +14,7 @@ default = true
14
14
 
15
15
  [project]
16
16
  name = "kon-coding-agent"
17
- version = "0.3.3"
17
+ version = "0.3.5"
18
18
  description = "Minimal coding agent"
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.12"
@@ -76,6 +76,7 @@ class LLMConfig(BaseModel):
76
76
  default_thinking_level: str
77
77
  system_prompt: SystemPromptConfig
78
78
  tool_call_idle_timeout_seconds: float = 180
79
+ request_timeout_seconds: float = 600
79
80
  auth: AuthConfig = AuthConfig()
80
81
 
81
82
 
@@ -11,6 +11,9 @@ default_thinking_level = "high"
11
11
  # Abort a tool call if it stays idle for this long during a turn.
12
12
  # Helps prevent stalled tool executions from hanging the agent loop.
13
13
  tool_call_idle_timeout_seconds = 180
14
+ # HTTP request timeout for LLM API calls (in seconds).
15
+ # Local models (e.g. llama.cpp) may need a higher value for long compaction requests.
16
+ request_timeout_seconds = 600
14
17
 
15
18
  [llm.auth]
16
19
  # Auth policy for OpenAI-compatible and Anthropic-compatible endpoints.
@@ -77,7 +77,7 @@ class ProviderConfig:
77
77
  model: str = ""
78
78
  max_tokens: int = 8192
79
79
  temperature: float | None = None
80
- thinking_level: str = "medium"
80
+ thinking_level: str = "high"
81
81
  provider: str | None = None
82
82
  session_id: str | None = None
83
83
  openai_compat_auth_mode: AuthMode = "auto"
@@ -10,6 +10,8 @@ from openai.types.chat import (
10
10
  ChatCompletionToolParam,
11
11
  )
12
12
 
13
+ from kon import config as kon_config
14
+
13
15
  from ...core.types import (
14
16
  AssistantMessage,
15
17
  ImageContent,
@@ -30,7 +32,7 @@ from ...core.types import (
30
32
  Usage,
31
33
  UserMessage,
32
34
  )
33
- from ..base import BaseProvider, LLMStream, ProviderConfig, resolve_api_key
35
+ from ..base import BaseProvider, LLMStream, ProviderConfig, is_local_base_url, resolve_api_key
34
36
  from .openai_compat import supports_developer_role
35
37
  from .sanitize import sanitize_surrogates
36
38
 
@@ -41,12 +43,13 @@ class OpenAICompletionsCompat:
41
43
  supports_developer_role: bool = True
42
44
  supports_reasoning_effort: bool = True
43
45
  max_tokens_field: Literal["max_tokens", "max_completion_tokens"] = "max_completion_tokens"
44
- thinking_format: Literal["openai", "zai", "qwen"] = "openai"
46
+ thinking_format: Literal["openai", "zai", "qwen", "llama_gemma"] = "openai"
45
47
 
46
48
 
47
- def _detect_compat(provider: str, base_url: str) -> OpenAICompletionsCompat:
49
+ def _detect_compat(provider: str, base_url: str, model: str = "") -> OpenAICompletionsCompat:
48
50
  normalized_provider = provider.lower()
49
51
  normalized_base_url = base_url.lower()
52
+ normalized_model = model.lower()
50
53
  is_zai = (
51
54
  normalized_provider == "zai"
52
55
  or normalized_provider == "zhipu"
@@ -61,6 +64,13 @@ def _detect_compat(provider: str, base_url: str) -> OpenAICompletionsCompat:
61
64
  thinking_format="zai",
62
65
  )
63
66
 
67
+ if is_local_base_url(base_url) and "gemma" in normalized_model:
68
+ return OpenAICompletionsCompat(
69
+ supports_developer_role=supports_developer_role(provider, base_url),
70
+ supports_reasoning_effort=False,
71
+ thinking_format="llama_gemma",
72
+ )
73
+
64
74
  return OpenAICompletionsCompat(
65
75
  supports_developer_role=supports_developer_role(provider, base_url)
66
76
  )
@@ -91,8 +101,14 @@ class OpenAICompletionsProvider(BaseProvider):
91
101
  "Set OPENAI_API_KEY or ZAI_API_KEY environment variable, "
92
102
  'or configure llm.auth.openai_compat = "auto"/"none" for local endpoints.'
93
103
  )
94
- self._client = AsyncOpenAI(api_key=api_key, base_url=config.base_url)
95
- self._compat = _detect_compat(config.provider or "", config.base_url or "")
104
+ self._client = AsyncOpenAI(
105
+ api_key=api_key,
106
+ base_url=config.base_url,
107
+ timeout=kon_config.llm.request_timeout_seconds,
108
+ )
109
+ self._compat = _detect_compat(
110
+ config.provider or "", config.base_url or "", config.model or ""
111
+ )
96
112
 
97
113
  async def _stream_impl(
98
114
  self,
@@ -138,7 +154,7 @@ class OpenAICompletionsProvider(BaseProvider):
138
154
  if compat.thinking_format == "zai":
139
155
  if thinking_level and thinking_level != "none":
140
156
  extra_body["thinking"] = {"type": "enabled"}
141
- elif compat.thinking_format == "qwen":
157
+ elif compat.thinking_format in {"qwen", "llama_gemma"}:
142
158
  extra_body["enable_thinking"] = bool(thinking_level and thinking_level != "none")
143
159
  elif (
144
160
  self.supports_reasoning_effort
@@ -238,11 +254,16 @@ class OpenAICompletionsProvider(BaseProvider):
238
254
 
239
255
  if system_prompt:
240
256
  role = "developer" if (compat and compat.supports_developer_role) else "system"
257
+ prompt_content = sanitize_surrogates(system_prompt)
258
+ if (
259
+ compat
260
+ and compat.thinking_format == "llama_gemma"
261
+ and self.config.thinking_level != "none"
262
+ and not prompt_content.startswith("<|think|>")
263
+ ):
264
+ prompt_content = "<|think|>" + prompt_content
241
265
  result.append(
242
- cast(
243
- ChatCompletionMessageParam,
244
- {"role": role, "content": sanitize_surrogates(system_prompt)},
245
- )
266
+ cast(ChatCompletionMessageParam, {"role": role, "content": prompt_content})
246
267
  )
247
268
 
248
269
  pending_images: list[ImageContent] = []
@@ -4,6 +4,8 @@ from typing import Any
4
4
 
5
5
  from openai import APIStatusError, AsyncOpenAI, RateLimitError
6
6
 
7
+ from kon import config as kon_config
8
+
7
9
  from ...core.types import (
8
10
  AssistantMessage,
9
11
  ImageContent,
@@ -51,6 +53,7 @@ class OpenAIResponsesProvider(BaseProvider):
51
53
  api_key=self.config.api_key,
52
54
  base_url=self.config.base_url,
53
55
  default_headers=self._headers,
56
+ timeout=kon_config.llm.request_timeout_seconds,
54
57
  )
55
58
  return self._client
56
59