1bcoder 0.1.10__tar.gz → 0.1.11__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.
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/1bcoder.egg-info/PKG-INFO +31 -4
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/PKG-INFO +31 -4
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/README.md +30 -3
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/advance.txt +3 -2
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/doc/PARAM.md +2 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/chat.py +192 -38
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/map_query.py +17 -8
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/pyproject.toml +1 -1
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/1bcoder.egg-info/SOURCES.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/1bcoder.egg-info/dependency_links.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/1bcoder.egg-info/entry_points.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/1bcoder.egg-info/requires.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/1bcoder.egg-info/top_level.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/LICENSE +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/__init__.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/ask.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/compact.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/concepts.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/fill.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/planning.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/scan.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/sqlite.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/agents/websearch.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/aliases.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/doc/FLOWS.md +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/doc/MCP.md +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/doc/OLLAMA_SERVER_PARAM.md +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/doc/PROC.md +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/doc/TRANSLATE.md +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/flows/__pycache__/commit_message.cpython-311.pyc +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/flows/commit_message.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/flows/grounding.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/flows/py_error_trace.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/flows/simargl_files.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/flows/webask.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/map.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/action-required.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/add-save.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/assist.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/collect-files.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/ctx_cut.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/extract-code.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/extract-files.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/extract-list.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/grounding-check.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/md.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/mdx.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/pattern-gate.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/regexp-extract.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/rude_words.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/scan-save.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/secret_check.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/sql_readonly_guard.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/proc/tempctx-cut.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/profiles.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/prompts/analysis.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/prompts/sumarise.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/prompts.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/AddFunction.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/AskProject.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/CheckRequirements.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/DockerMySQL.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/DockerNginx.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/DockerPython.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/DockerStack.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/DuckDuckGoInstant.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/EnvTemplate.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/Explain.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/ExploreProjectStructure.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/GitIgnorePython.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/MySQLDump.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/NewScript.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/PipFreeze.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/PyPI.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/Refactor.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/RunAndFix.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/SQLiteSchema.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/Translate.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/WikiPage.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/WikiSearch.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/auto-bkup.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/edit-control.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/parallel_call.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/personal/content/create-regular-content.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/personal/content/plan.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/personal/test/collect-data-from-test-environment.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/plan.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/remote/create-content-on-remote-server.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/set_ctx.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/simargl-cli_index_files.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/simargl-cli_index_units.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/simargl-cli_search.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/team-map-worker.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/team-search-worker.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/team-summarize.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/team-tree-worker.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/test.txt +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/teams/code-analysis.yaml +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/map_index.py +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/setup.cfg +0 -0
- {1bcoder-0.1.10 → 1bcoder-0.1.11}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: 1bcoder
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: AI coding assistant agent for 1B–7B local models (Ollama, LMStudio, llama.cpp). Terminal REPL with file editing, project map, agents, scripts, and parallel multi-model queries.
|
|
5
5
|
Project-URL: Homepage, https://github.com/szholobetsky/1bcoder
|
|
6
6
|
Project-URL: Repository, https://github.com/szholobetsky/1bcoder
|
|
@@ -13,6 +13,8 @@ Requires-Dist: tqdm>=4.64
|
|
|
13
13
|
Requires-Dist: rich>=13.0
|
|
14
14
|
Dynamic: license-file
|
|
15
15
|
|
|
16
|
+

|
|
17
|
+
|
|
16
18
|
# 1bcoder
|
|
17
19
|
|
|
18
20
|
AI coding assistant for small local models (0.5B–4B) — runs via [Ollama](https://ollama.com), [LMStudio](https://lmstudio.ai), or any OpenAI-compatible backend.
|
|
@@ -128,7 +130,7 @@ Tasks that require the model to decide *what to look at* — refactoring across
|
|
|
128
130
|
- **Command autocorrection** — typos in command names, file paths, and keywords are detected and fixed automatically before execution, for both human input and agent actions
|
|
129
131
|
- **`/tree [path]`** — display directory tree of the whole project or any subtree; ask to inject into context (or pass `ctx` to skip the prompt)
|
|
130
132
|
- **`/find <pattern>`** — search filenames and file content with regex; supports `-f`/`-c`/`-i`/`--ext` flags; highlights matches, asks to inject results into context; sets `{{find_files}}` after every search; **`/find <terms> -r`** ranked BM25 mode returns top-10 files by relevance; hidden directories (`.git`, `.venv`, etc.) excluded automatically
|
|
131
|
-
- AI proposes a **one-line fix** (`/fix`)
|
|
133
|
+
- AI proposes a **one-line fix** (`/fix`), a **SEARCH/REPLACE patch** (`/patch`), or a **FIM-based fix** (`/fim`) — always shows a unified diff before applying
|
|
132
134
|
- **Apply AI code blocks directly** with `/edit <file> code` (new/full file) or `/patch <file> code` (SEARCH/REPLACE from reply, no line numbers needed) — preferred for agent mode
|
|
133
135
|
- **`<think>` tag support** — reasoning blocks shown in terminal by default; `/think hide` suppresses terminal display; `/think include` keeps reasoning in context for chained turns
|
|
134
136
|
- Run shell commands and inject their output with `/run`
|
|
@@ -453,10 +455,12 @@ Then configure `/translate` to use it:
|
|
|
453
455
|
| Command | Description |
|
|
454
456
|
|---|---|
|
|
455
457
|
| `/fix <file> [start-end] [hint]` | AI proposes one-line fix, shows diff, asks to apply |
|
|
458
|
+
| `/fim <file> <line or start-end> [-w N] [hint]` | FIM-based fix — model rewrites the marked section, shows unified diff |
|
|
456
459
|
| `/patch <file> [start-end] [hint]` | AI proposes SEARCH/REPLACE block, shows unified diff |
|
|
457
460
|
| `/patch <file> code` | Apply SEARCH/REPLACE block from last AI reply (no new LLM call) |
|
|
458
461
|
|
|
459
|
-
`/fix`
|
|
462
|
+
`/fix` asks the model to output `LINE N: content` — simple but small models often lose indentation.
|
|
463
|
+
`/fim` (Fill-In-the-Middle) marks the target line(s) with `<<<...>>>` inside the full file, asks the model to return the corrected file, then diffs the result — no output format to learn, grammar constraints come from the surrounding code. Use `-w N` to limit context to N lines around the target when the file is larger than the context window.
|
|
460
464
|
`/patch` works better with larger models (7B+) and can replace multiple consecutive lines.
|
|
461
465
|
`/patch <file> code` is the preferred agent mode edit — the agent writes the SEARCH/REPLACE block in its reply, then calls `/patch <file> code` to apply it without needing line numbers.
|
|
462
466
|
|
|
@@ -465,6 +469,9 @@ When `/patch` fails to find the SEARCH text it shows a diagnostic diff — the S
|
|
|
465
469
|
```
|
|
466
470
|
/fix main.py
|
|
467
471
|
/fix main.py 2-2 wrong operator
|
|
472
|
+
/fim main.py 3 replace != with ==
|
|
473
|
+
/fim main.py 3-5 fix the logic
|
|
474
|
+
/fim huge_file.py 14567 -w 20 fix indentation
|
|
468
475
|
/patch main.py 10-40 fix the loop logic
|
|
469
476
|
/patch main.py code
|
|
470
477
|
```
|
|
@@ -1739,7 +1746,7 @@ On Windows: hold `Shift` and drag with the left mouse button to select and copy
|
|
|
1739
1746
|
## Tips for 1B models
|
|
1740
1747
|
|
|
1741
1748
|
- **Start small.** Use `/read file.py 10-25` instead of loading the whole file. Short context = better focus.
|
|
1742
|
-
- **
|
|
1749
|
+
- **Try `/fim` for tricky fixes.** FIM-based editing activates the model's grammar knowledge through surrounding code context — more reliable than `/fix` for indentation and multi-line logic. Use `-w 20` for large files.
|
|
1743
1750
|
- **Build a map first.** Run `/map index .` at the start of a session, then use `/map find` to load only the relevant parts into context.
|
|
1744
1751
|
- **Use scripts.** Scripts make multi-step work reproducible — the model only needs to handle one step at a time.
|
|
1745
1752
|
- **Capture workflows.** After solving a task manually, run `/script create ctx` to save the exact steps as a reusable script.
|
|
@@ -1796,6 +1803,26 @@ For human input, the corrected command is shown with `[fix?]` and you are asked
|
|
|
1796
1803
|
|
|
1797
1804
|
---
|
|
1798
1805
|
|
|
1806
|
+
## Part of the SIMARGL toolkit
|
|
1807
|
+
|
|
1808
|
+
1bcoder is one of four tools that together form an **intellectual development support system**:
|
|
1809
|
+
|
|
1810
|
+
| Tool | Role |
|
|
1811
|
+
|---|---|
|
|
1812
|
+
| **[simargl](https://github.com/szholobetsky/simargl)** | Task-to-code retrieval — given a task description, finds which files and modules are likely affected, using semantic similarity over git history |
|
|
1813
|
+
| **[svitovyd](https://github.com/szholobetsky/svitovyd)** | Project map — scans any codebase and produces a structural map of definitions and cross-file dependencies; exposes it as an MCP server |
|
|
1814
|
+
| **[1bcoder](https://github.com/szholobetsky/1bcoder)** | AI coding assistant for small local models — surgical context management, agents, parallel inference, proc scripts |
|
|
1815
|
+
| **[yasna](https://github.com/szholobetsky/yasna)** | Session memory — indexes conversations from all AI agents so you can find what was discussed, when, and where |
|
|
1816
|
+
|
|
1817
|
+
- **simargl** answers: *what code is related to this task?*
|
|
1818
|
+
- **svitovyd** answers: *how is the code structured and what depends on what?*
|
|
1819
|
+
- **1bcoder** answers: *how do I work with local models efficiently?*
|
|
1820
|
+
- **yasna** answers: *where did I already discuss this?*
|
|
1821
|
+
|
|
1822
|
+
Together they cover the full development loop: understand the codebase, find relevant history, work with AI locally, remember what was decided.
|
|
1823
|
+
|
|
1824
|
+
---
|
|
1825
|
+
|
|
1799
1826
|
**(c) 2026 Stanislav Zholobetskyi**
|
|
1800
1827
|
Institute for Information Recording, National Academy of Sciences of Ukraine, Kyiv
|
|
1801
1828
|
*PhD research: «Intelligent Technology for Software Development and Maintenance Support»*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: 1bcoder
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: AI coding assistant agent for 1B–7B local models (Ollama, LMStudio, llama.cpp). Terminal REPL with file editing, project map, agents, scripts, and parallel multi-model queries.
|
|
5
5
|
Project-URL: Homepage, https://github.com/szholobetsky/1bcoder
|
|
6
6
|
Project-URL: Repository, https://github.com/szholobetsky/1bcoder
|
|
@@ -13,6 +13,8 @@ Requires-Dist: tqdm>=4.64
|
|
|
13
13
|
Requires-Dist: rich>=13.0
|
|
14
14
|
Dynamic: license-file
|
|
15
15
|
|
|
16
|
+

|
|
17
|
+
|
|
16
18
|
# 1bcoder
|
|
17
19
|
|
|
18
20
|
AI coding assistant for small local models (0.5B–4B) — runs via [Ollama](https://ollama.com), [LMStudio](https://lmstudio.ai), or any OpenAI-compatible backend.
|
|
@@ -128,7 +130,7 @@ Tasks that require the model to decide *what to look at* — refactoring across
|
|
|
128
130
|
- **Command autocorrection** — typos in command names, file paths, and keywords are detected and fixed automatically before execution, for both human input and agent actions
|
|
129
131
|
- **`/tree [path]`** — display directory tree of the whole project or any subtree; ask to inject into context (or pass `ctx` to skip the prompt)
|
|
130
132
|
- **`/find <pattern>`** — search filenames and file content with regex; supports `-f`/`-c`/`-i`/`--ext` flags; highlights matches, asks to inject results into context; sets `{{find_files}}` after every search; **`/find <terms> -r`** ranked BM25 mode returns top-10 files by relevance; hidden directories (`.git`, `.venv`, etc.) excluded automatically
|
|
131
|
-
- AI proposes a **one-line fix** (`/fix`)
|
|
133
|
+
- AI proposes a **one-line fix** (`/fix`), a **SEARCH/REPLACE patch** (`/patch`), or a **FIM-based fix** (`/fim`) — always shows a unified diff before applying
|
|
132
134
|
- **Apply AI code blocks directly** with `/edit <file> code` (new/full file) or `/patch <file> code` (SEARCH/REPLACE from reply, no line numbers needed) — preferred for agent mode
|
|
133
135
|
- **`<think>` tag support** — reasoning blocks shown in terminal by default; `/think hide` suppresses terminal display; `/think include` keeps reasoning in context for chained turns
|
|
134
136
|
- Run shell commands and inject their output with `/run`
|
|
@@ -453,10 +455,12 @@ Then configure `/translate` to use it:
|
|
|
453
455
|
| Command | Description |
|
|
454
456
|
|---|---|
|
|
455
457
|
| `/fix <file> [start-end] [hint]` | AI proposes one-line fix, shows diff, asks to apply |
|
|
458
|
+
| `/fim <file> <line or start-end> [-w N] [hint]` | FIM-based fix — model rewrites the marked section, shows unified diff |
|
|
456
459
|
| `/patch <file> [start-end] [hint]` | AI proposes SEARCH/REPLACE block, shows unified diff |
|
|
457
460
|
| `/patch <file> code` | Apply SEARCH/REPLACE block from last AI reply (no new LLM call) |
|
|
458
461
|
|
|
459
|
-
`/fix`
|
|
462
|
+
`/fix` asks the model to output `LINE N: content` — simple but small models often lose indentation.
|
|
463
|
+
`/fim` (Fill-In-the-Middle) marks the target line(s) with `<<<...>>>` inside the full file, asks the model to return the corrected file, then diffs the result — no output format to learn, grammar constraints come from the surrounding code. Use `-w N` to limit context to N lines around the target when the file is larger than the context window.
|
|
460
464
|
`/patch` works better with larger models (7B+) and can replace multiple consecutive lines.
|
|
461
465
|
`/patch <file> code` is the preferred agent mode edit — the agent writes the SEARCH/REPLACE block in its reply, then calls `/patch <file> code` to apply it without needing line numbers.
|
|
462
466
|
|
|
@@ -465,6 +469,9 @@ When `/patch` fails to find the SEARCH text it shows a diagnostic diff — the S
|
|
|
465
469
|
```
|
|
466
470
|
/fix main.py
|
|
467
471
|
/fix main.py 2-2 wrong operator
|
|
472
|
+
/fim main.py 3 replace != with ==
|
|
473
|
+
/fim main.py 3-5 fix the logic
|
|
474
|
+
/fim huge_file.py 14567 -w 20 fix indentation
|
|
468
475
|
/patch main.py 10-40 fix the loop logic
|
|
469
476
|
/patch main.py code
|
|
470
477
|
```
|
|
@@ -1739,7 +1746,7 @@ On Windows: hold `Shift` and drag with the left mouse button to select and copy
|
|
|
1739
1746
|
## Tips for 1B models
|
|
1740
1747
|
|
|
1741
1748
|
- **Start small.** Use `/read file.py 10-25` instead of loading the whole file. Short context = better focus.
|
|
1742
|
-
- **
|
|
1749
|
+
- **Try `/fim` for tricky fixes.** FIM-based editing activates the model's grammar knowledge through surrounding code context — more reliable than `/fix` for indentation and multi-line logic. Use `-w 20` for large files.
|
|
1743
1750
|
- **Build a map first.** Run `/map index .` at the start of a session, then use `/map find` to load only the relevant parts into context.
|
|
1744
1751
|
- **Use scripts.** Scripts make multi-step work reproducible — the model only needs to handle one step at a time.
|
|
1745
1752
|
- **Capture workflows.** After solving a task manually, run `/script create ctx` to save the exact steps as a reusable script.
|
|
@@ -1796,6 +1803,26 @@ For human input, the corrected command is shown with `[fix?]` and you are asked
|
|
|
1796
1803
|
|
|
1797
1804
|
---
|
|
1798
1805
|
|
|
1806
|
+
## Part of the SIMARGL toolkit
|
|
1807
|
+
|
|
1808
|
+
1bcoder is one of four tools that together form an **intellectual development support system**:
|
|
1809
|
+
|
|
1810
|
+
| Tool | Role |
|
|
1811
|
+
|---|---|
|
|
1812
|
+
| **[simargl](https://github.com/szholobetsky/simargl)** | Task-to-code retrieval — given a task description, finds which files and modules are likely affected, using semantic similarity over git history |
|
|
1813
|
+
| **[svitovyd](https://github.com/szholobetsky/svitovyd)** | Project map — scans any codebase and produces a structural map of definitions and cross-file dependencies; exposes it as an MCP server |
|
|
1814
|
+
| **[1bcoder](https://github.com/szholobetsky/1bcoder)** | AI coding assistant for small local models — surgical context management, agents, parallel inference, proc scripts |
|
|
1815
|
+
| **[yasna](https://github.com/szholobetsky/yasna)** | Session memory — indexes conversations from all AI agents so you can find what was discussed, when, and where |
|
|
1816
|
+
|
|
1817
|
+
- **simargl** answers: *what code is related to this task?*
|
|
1818
|
+
- **svitovyd** answers: *how is the code structured and what depends on what?*
|
|
1819
|
+
- **1bcoder** answers: *how do I work with local models efficiently?*
|
|
1820
|
+
- **yasna** answers: *where did I already discuss this?*
|
|
1821
|
+
|
|
1822
|
+
Together they cover the full development loop: understand the codebase, find relevant history, work with AI locally, remember what was decided.
|
|
1823
|
+
|
|
1824
|
+
---
|
|
1825
|
+
|
|
1799
1826
|
**(c) 2026 Stanislav Zholobetskyi**
|
|
1800
1827
|
Institute for Information Recording, National Academy of Sciences of Ukraine, Kyiv
|
|
1801
1828
|
*PhD research: «Intelligent Technology for Software Development and Maintenance Support»*
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
1
3
|
# 1bcoder
|
|
2
4
|
|
|
3
5
|
AI coding assistant for small local models (0.5B–4B) — runs via [Ollama](https://ollama.com), [LMStudio](https://lmstudio.ai), or any OpenAI-compatible backend.
|
|
@@ -113,7 +115,7 @@ Tasks that require the model to decide *what to look at* — refactoring across
|
|
|
113
115
|
- **Command autocorrection** — typos in command names, file paths, and keywords are detected and fixed automatically before execution, for both human input and agent actions
|
|
114
116
|
- **`/tree [path]`** — display directory tree of the whole project or any subtree; ask to inject into context (or pass `ctx` to skip the prompt)
|
|
115
117
|
- **`/find <pattern>`** — search filenames and file content with regex; supports `-f`/`-c`/`-i`/`--ext` flags; highlights matches, asks to inject results into context; sets `{{find_files}}` after every search; **`/find <terms> -r`** ranked BM25 mode returns top-10 files by relevance; hidden directories (`.git`, `.venv`, etc.) excluded automatically
|
|
116
|
-
- AI proposes a **one-line fix** (`/fix`)
|
|
118
|
+
- AI proposes a **one-line fix** (`/fix`), a **SEARCH/REPLACE patch** (`/patch`), or a **FIM-based fix** (`/fim`) — always shows a unified diff before applying
|
|
117
119
|
- **Apply AI code blocks directly** with `/edit <file> code` (new/full file) or `/patch <file> code` (SEARCH/REPLACE from reply, no line numbers needed) — preferred for agent mode
|
|
118
120
|
- **`<think>` tag support** — reasoning blocks shown in terminal by default; `/think hide` suppresses terminal display; `/think include` keeps reasoning in context for chained turns
|
|
119
121
|
- Run shell commands and inject their output with `/run`
|
|
@@ -438,10 +440,12 @@ Then configure `/translate` to use it:
|
|
|
438
440
|
| Command | Description |
|
|
439
441
|
|---|---|
|
|
440
442
|
| `/fix <file> [start-end] [hint]` | AI proposes one-line fix, shows diff, asks to apply |
|
|
443
|
+
| `/fim <file> <line or start-end> [-w N] [hint]` | FIM-based fix — model rewrites the marked section, shows unified diff |
|
|
441
444
|
| `/patch <file> [start-end] [hint]` | AI proposes SEARCH/REPLACE block, shows unified diff |
|
|
442
445
|
| `/patch <file> code` | Apply SEARCH/REPLACE block from last AI reply (no new LLM call) |
|
|
443
446
|
|
|
444
|
-
`/fix`
|
|
447
|
+
`/fix` asks the model to output `LINE N: content` — simple but small models often lose indentation.
|
|
448
|
+
`/fim` (Fill-In-the-Middle) marks the target line(s) with `<<<...>>>` inside the full file, asks the model to return the corrected file, then diffs the result — no output format to learn, grammar constraints come from the surrounding code. Use `-w N` to limit context to N lines around the target when the file is larger than the context window.
|
|
445
449
|
`/patch` works better with larger models (7B+) and can replace multiple consecutive lines.
|
|
446
450
|
`/patch <file> code` is the preferred agent mode edit — the agent writes the SEARCH/REPLACE block in its reply, then calls `/patch <file> code` to apply it without needing line numbers.
|
|
447
451
|
|
|
@@ -450,6 +454,9 @@ When `/patch` fails to find the SEARCH text it shows a diagnostic diff — the S
|
|
|
450
454
|
```
|
|
451
455
|
/fix main.py
|
|
452
456
|
/fix main.py 2-2 wrong operator
|
|
457
|
+
/fim main.py 3 replace != with ==
|
|
458
|
+
/fim main.py 3-5 fix the logic
|
|
459
|
+
/fim huge_file.py 14567 -w 20 fix indentation
|
|
453
460
|
/patch main.py 10-40 fix the loop logic
|
|
454
461
|
/patch main.py code
|
|
455
462
|
```
|
|
@@ -1724,7 +1731,7 @@ On Windows: hold `Shift` and drag with the left mouse button to select and copy
|
|
|
1724
1731
|
## Tips for 1B models
|
|
1725
1732
|
|
|
1726
1733
|
- **Start small.** Use `/read file.py 10-25` instead of loading the whole file. Short context = better focus.
|
|
1727
|
-
- **
|
|
1734
|
+
- **Try `/fim` for tricky fixes.** FIM-based editing activates the model's grammar knowledge through surrounding code context — more reliable than `/fix` for indentation and multi-line logic. Use `-w 20` for large files.
|
|
1728
1735
|
- **Build a map first.** Run `/map index .` at the start of a session, then use `/map find` to load only the relevant parts into context.
|
|
1729
1736
|
- **Use scripts.** Scripts make multi-step work reproducible — the model only needs to handle one step at a time.
|
|
1730
1737
|
- **Capture workflows.** After solving a task manually, run `/script create ctx` to save the exact steps as a reusable script.
|
|
@@ -1781,6 +1788,26 @@ For human input, the corrected command is shown with `[fix?]` and you are asked
|
|
|
1781
1788
|
|
|
1782
1789
|
---
|
|
1783
1790
|
|
|
1791
|
+
## Part of the SIMARGL toolkit
|
|
1792
|
+
|
|
1793
|
+
1bcoder is one of four tools that together form an **intellectual development support system**:
|
|
1794
|
+
|
|
1795
|
+
| Tool | Role |
|
|
1796
|
+
|---|---|
|
|
1797
|
+
| **[simargl](https://github.com/szholobetsky/simargl)** | Task-to-code retrieval — given a task description, finds which files and modules are likely affected, using semantic similarity over git history |
|
|
1798
|
+
| **[svitovyd](https://github.com/szholobetsky/svitovyd)** | Project map — scans any codebase and produces a structural map of definitions and cross-file dependencies; exposes it as an MCP server |
|
|
1799
|
+
| **[1bcoder](https://github.com/szholobetsky/1bcoder)** | AI coding assistant for small local models — surgical context management, agents, parallel inference, proc scripts |
|
|
1800
|
+
| **[yasna](https://github.com/szholobetsky/yasna)** | Session memory — indexes conversations from all AI agents so you can find what was discussed, when, and where |
|
|
1801
|
+
|
|
1802
|
+
- **simargl** answers: *what code is related to this task?*
|
|
1803
|
+
- **svitovyd** answers: *how is the code structured and what depends on what?*
|
|
1804
|
+
- **1bcoder** answers: *how do I work with local models efficiently?*
|
|
1805
|
+
- **yasna** answers: *where did I already discuss this?*
|
|
1806
|
+
|
|
1807
|
+
Together they cover the full development loop: understand the codebase, find relevant history, work with AI locally, remember what was decided.
|
|
1808
|
+
|
|
1809
|
+
---
|
|
1810
|
+
|
|
1784
1811
|
**(c) 2026 Stanislav Zholobetskyi**
|
|
1785
1812
|
Institute for Information Recording, National Academy of Sciences of Ukraine, Kyiv
|
|
1786
1813
|
*PhD research: «Intelligent Technology for Software Development and Maintenance Support»*
|
|
@@ -13,6 +13,7 @@ system =
|
|
|
13
13
|
|
|
14
14
|
How to write files:
|
|
15
15
|
- To MODIFY an existing file: write a SEARCH/REPLACE block, then ACTION: /patch <file> code
|
|
16
|
+
Or use FIM for targeted fixes: ACTION: /fim <file> <line or start-end> <hint>
|
|
16
17
|
- To INSERT new code at a line: write the code block, then ACTION: /insert <file> <line> code
|
|
17
18
|
- To CREATE or fully REPLACE a file: write the full code block, then ACTION: /save <file> code
|
|
18
19
|
|
|
@@ -24,7 +25,7 @@ system =
|
|
|
24
25
|
>>>>>>> REPLACE
|
|
25
26
|
|
|
26
27
|
Rules:
|
|
27
|
-
- /
|
|
28
|
+
- /readln a file before editing it
|
|
28
29
|
- /bkup save <file> before modifying important files
|
|
29
30
|
- /run to test after applying a fix
|
|
30
31
|
|
|
@@ -40,7 +41,7 @@ tools =
|
|
|
40
41
|
bkup
|
|
41
42
|
diff
|
|
42
43
|
patch
|
|
43
|
-
|
|
44
|
+
fim
|
|
44
45
|
tree
|
|
45
46
|
find
|
|
46
47
|
map
|
|
@@ -17,6 +17,8 @@ These are handled by 1bcoder directly and are not forwarded to the model API.
|
|
|
17
17
|
| `think_exclude` | `true` | Strip `<think>…</think>` blocks from context (blocks are shown in terminal only). Set `false` to keep reasoning in context for multi-turn chains. |
|
|
18
18
|
| `ask_limit` | 8000 | Max characters of `/ask` tool output kept in context. |
|
|
19
19
|
| `ask_show` | 500 | Characters shown in terminal when output is truncated. |
|
|
20
|
+
| `run_timeout` | 30 | Timeout in seconds for `/run` shell commands. Set to `0` to disable (no timeout). Useful for long-running CLI tools like `simargl search`. |
|
|
21
|
+
| `log` | `false` | Print full request details before each LLM call: URL, model, message count, options. Also prints HTTP response headers on error. Useful for debugging 500 errors or unexpected model behaviour. |
|
|
20
22
|
|
|
21
23
|
---
|
|
22
24
|
|
|
@@ -225,7 +225,7 @@ PROFILES_FILE = os.path.join(BCODER_DIR, "profiles.txt")
|
|
|
225
225
|
GLOBAL_PROFILES_FILE = os.path.join(HOME_BCODER_DIR, "profiles.txt")
|
|
226
226
|
|
|
227
227
|
DEFAULT_AGENT_TOOLS = [
|
|
228
|
-
"read", "tree", "find", "insert", "save", "
|
|
228
|
+
"read", "readln", "tree", "find", "insert", "save", "fim",
|
|
229
229
|
]
|
|
230
230
|
|
|
231
231
|
DEFAULT_AGENT_TOOLS_ADVANCED = [
|
|
@@ -247,33 +247,19 @@ AGENT_SYSTEM_BASIC = """\
|
|
|
247
247
|
You are a coding assistant. Complete the task using the available tools.
|
|
248
248
|
|
|
249
249
|
To call a tool, write ACTION: on its own line. Wait for [tool result].
|
|
250
|
-
Run
|
|
251
|
-
When
|
|
250
|
+
Run one action at a time until the task is complete.
|
|
251
|
+
When done, write a short summary with no ACTION and end with: Task is complete.
|
|
252
252
|
|
|
253
|
-
|
|
254
|
-
ACTION: /
|
|
255
|
-
ACTION: /
|
|
253
|
+
To fix or edit a file:
|
|
254
|
+
ACTION: /fim <file> <description of what to fix>
|
|
255
|
+
Example: ACTION: /fim calc.py fix the division by zero bug
|
|
256
|
+
Example: ACTION: /fim main.py fix the indentation on line 5
|
|
256
257
|
|
|
257
|
-
To
|
|
258
|
-
|
|
259
|
-
2. Then call:
|
|
260
|
-
ACTION: /insert <file> <line> code ← insert code block before line N
|
|
261
|
-
ACTION: /insert <file> <line> <text> ← insert literal text before line N
|
|
262
|
-
ACTION: /patch <file> code ← apply SEARCH/REPLACE block
|
|
263
|
-
ACTION: /save <file> code ← save or overwrite whole file
|
|
258
|
+
To read a file:
|
|
259
|
+
ACTION: /read <file>
|
|
264
260
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
SEARCH/REPLACE format for /patch:
|
|
268
|
-
<<<<<<< SEARCH
|
|
269
|
-
exact lines to replace
|
|
270
|
-
=======
|
|
271
|
-
new lines
|
|
272
|
-
>>>>>>> REPLACE
|
|
273
|
-
|
|
274
|
-
Rules:
|
|
275
|
-
- If you don't know the project structure, start with ACTION: /tree
|
|
276
|
-
- Always /read a file before inserting or patching it.
|
|
261
|
+
To create or fully replace a file: write the full code block, then:
|
|
262
|
+
ACTION: /save <file> code
|
|
277
263
|
|
|
278
264
|
Available tools:
|
|
279
265
|
{tool_list}
|
|
@@ -287,6 +273,7 @@ When the task is complete, write a short summary and end with: Task is complete.
|
|
|
287
273
|
|
|
288
274
|
How to write files (the keyword "code" means: use the last ``` ``` block written above):
|
|
289
275
|
- To MODIFY an existing file: write a SEARCH/REPLACE block, then ACTION: /patch <file> code
|
|
276
|
+
Or use FIM for targeted fixes: ACTION: /fim <file> <line or start-end> <hint>
|
|
290
277
|
- To INSERT new code at a line: write the code block, then ACTION: /insert <file> <line> code
|
|
291
278
|
- To CREATE or fully REPLACE a file: write the full code block, then ACTION: /save <file> code
|
|
292
279
|
|
|
@@ -298,7 +285,7 @@ new lines
|
|
|
298
285
|
>>>>>>> REPLACE
|
|
299
286
|
|
|
300
287
|
Rules:
|
|
301
|
-
- /
|
|
288
|
+
- /readln a file before editing it
|
|
302
289
|
- /bkup save <file> before modifying important files
|
|
303
290
|
- /run to test after applying a fix
|
|
304
291
|
|
|
@@ -339,7 +326,7 @@ FIX_SYSTEM = (
|
|
|
339
326
|
"You are a code repair tool. "
|
|
340
327
|
"Respond with ONLY the single most important fix in this exact format:\n"
|
|
341
328
|
"LINE <number>: <corrected line content>\n"
|
|
342
|
-
"One fix only. No explanation. No other text.
|
|
329
|
+
"One fix only. No explanation. No other text."
|
|
343
330
|
)
|
|
344
331
|
|
|
345
332
|
PATCH_SYSTEM = (
|
|
@@ -450,6 +437,16 @@ Commands
|
|
|
450
437
|
/fix main.py 2-2
|
|
451
438
|
/fix main.py 2-2 wrong operator
|
|
452
439
|
|
|
440
|
+
/fim <file> [line or start-end] [-w N] [hint]
|
|
441
|
+
FIM-based fix. Marks the line(s), passes file to model, diffs the result.
|
|
442
|
+
Without a line number: passes the whole file with hint only (agent fallback mode).
|
|
443
|
+
-w N pass only N lines of context around the marked section (for large files).
|
|
444
|
+
e.g. /fim main.py 3
|
|
445
|
+
/fim main.py 3 replace != with ==
|
|
446
|
+
/fim main.py 3-5 fix the logic
|
|
447
|
+
/fim huge.py 14567 -w 20 fix indentation
|
|
448
|
+
/fim main.py fix the division by zero bug
|
|
449
|
+
|
|
453
450
|
/patch <file> [start-end] [hint]
|
|
454
451
|
AI proposes a multi-line SEARCH/REPLACE edit. Shows unified diff before applying.
|
|
455
452
|
Better for 7B+ models. Use /fix for 1B models.
|
|
@@ -874,6 +871,7 @@ Output capture operators (work with any command — LLM reply, tool, proc):
|
|
|
874
871
|
\\!term exclude entire block if any child contains term
|
|
875
872
|
-term show ONLY child lines containing term
|
|
876
873
|
-!term hide child lines containing term
|
|
874
|
+
+term like -term but also hides files with no matching children
|
|
877
875
|
e.g. /map find register
|
|
878
876
|
/map find \\register !mock
|
|
879
877
|
/map find auth \\UserService -!deprecated -y
|
|
@@ -1271,6 +1269,54 @@ def ai_fix(base_url, model, content, label, hint="", on_chunk=None, provider="ol
|
|
|
1271
1269
|
return None, raw
|
|
1272
1270
|
|
|
1273
1271
|
|
|
1272
|
+
def ai_fill(base_url, model, file_lines, start, end, hint="", on_chunk=None, provider="ollama"):
|
|
1273
|
+
"""FIM-based fix: marks line range in the whole file, asks model for corrected file.
|
|
1274
|
+
If start is None: no marker — whole file passed with hint only (agent fallback mode)."""
|
|
1275
|
+
if start is None:
|
|
1276
|
+
file_content = "".join(file_lines)
|
|
1277
|
+
user_msg = file_content + "\nFix the issue. Output the complete corrected file."
|
|
1278
|
+
else:
|
|
1279
|
+
marked = list(file_lines)
|
|
1280
|
+
if start == end:
|
|
1281
|
+
marked[start - 1] = f"<<<{file_lines[start - 1].rstrip()}>>>\n"
|
|
1282
|
+
else:
|
|
1283
|
+
marked[start - 1] = "<<<\n" + file_lines[start - 1]
|
|
1284
|
+
marked[end - 1] = file_lines[end - 1].rstrip() + "\n>>>\n"
|
|
1285
|
+
file_content = "".join(marked)
|
|
1286
|
+
user_msg = file_content + "\nFix the <<<...>>> section. Output the complete corrected file."
|
|
1287
|
+
if hint:
|
|
1288
|
+
user_msg = f"{hint}\n\n{user_msg}"
|
|
1289
|
+
msgs = [{"role": "user", "content": user_msg}]
|
|
1290
|
+
chunks = []
|
|
1291
|
+
if provider == "openai":
|
|
1292
|
+
with requests.post(
|
|
1293
|
+
f"{base_url}/v1/chat/completions",
|
|
1294
|
+
json={"model": model, "messages": msgs, "stream": True},
|
|
1295
|
+
stream=True, timeout=120,
|
|
1296
|
+
) as resp:
|
|
1297
|
+
resp.raise_for_status()
|
|
1298
|
+
_parse_openai_stream(resp, on_chunk, chunks)
|
|
1299
|
+
else:
|
|
1300
|
+
with requests.post(
|
|
1301
|
+
f"{base_url}/api/chat",
|
|
1302
|
+
json={"model": model, "messages": msgs, "stream": True},
|
|
1303
|
+
stream=True, timeout=120,
|
|
1304
|
+
) as resp:
|
|
1305
|
+
resp.raise_for_status()
|
|
1306
|
+
for line in resp.iter_lines():
|
|
1307
|
+
if not line:
|
|
1308
|
+
continue
|
|
1309
|
+
data = json.loads(line)
|
|
1310
|
+
chunk = data.get("message", {}).get("content", "")
|
|
1311
|
+
if chunk:
|
|
1312
|
+
if on_chunk:
|
|
1313
|
+
on_chunk(chunk)
|
|
1314
|
+
chunks.append(chunk)
|
|
1315
|
+
if data.get("done"):
|
|
1316
|
+
break
|
|
1317
|
+
return "".join(chunks)
|
|
1318
|
+
|
|
1319
|
+
|
|
1274
1320
|
def _parse_patch(text):
|
|
1275
1321
|
"""Extract (search_text, replace_text) from a SEARCH/REPLACE block, or (None, None)."""
|
|
1276
1322
|
m = re.search(
|
|
@@ -1984,7 +2030,7 @@ def _map_patch_remove(map_path: str, rel_prefix: str) -> int:
|
|
|
1984
2030
|
|
|
1985
2031
|
_KNOWN_CMDS = [
|
|
1986
2032
|
"/read", "/readln", "/insert", "/edit", "/save", "/run", "/script", "/mcp",
|
|
1987
|
-
"/parallel", "/patch", "/fix", "/bkup", "/diff", "/agent", "/tree",
|
|
2033
|
+
"/parallel", "/patch", "/fix", "/fim", "/bkup", "/diff", "/agent", "/tree",
|
|
1988
2034
|
"/find", "/map", "/ctx", "/think", "/format", "/param", "/model",
|
|
1989
2035
|
"/host", "/help", "/init", "/clear", "/exit",
|
|
1990
2036
|
"/prompt", "/proc", "/team", "/var", "/config", "/alias",
|
|
@@ -2326,6 +2372,7 @@ class CoderCLI:
|
|
|
2326
2372
|
self._last_find_results: list = [] # numbered results from last /proj find
|
|
2327
2373
|
self._history: list[str] = []
|
|
2328
2374
|
self.cmd_history: list[str] = [] # all /commands typed this session
|
|
2375
|
+
self.log_requests: bool = False # /param log true — print request body + error detail
|
|
2329
2376
|
# enable readline history if available
|
|
2330
2377
|
try:
|
|
2331
2378
|
import readline
|
|
@@ -2376,6 +2423,9 @@ class CoderCLI:
|
|
|
2376
2423
|
if self.provider == "openai":
|
|
2377
2424
|
body = {"model": self.model, "messages": messages, "stream": True}
|
|
2378
2425
|
body.update(self.params)
|
|
2426
|
+
if self.log_requests:
|
|
2427
|
+
print(f" [log] POST {self.base_url}/v1/chat/completions")
|
|
2428
|
+
print(f" [log] model={self.model} messages={len(messages)} params={self.params}")
|
|
2379
2429
|
with requests.post(
|
|
2380
2430
|
f"{self.base_url}/v1/chat/completions",
|
|
2381
2431
|
json=body, stream=True, timeout=self.timeout,
|
|
@@ -2436,6 +2486,9 @@ class CoderCLI:
|
|
|
2436
2486
|
else:
|
|
2437
2487
|
opts = {"num_ctx": self.num_ctx}
|
|
2438
2488
|
opts.update(self.params)
|
|
2489
|
+
if self.log_requests:
|
|
2490
|
+
print(f" [log] POST {self.base_url}/api/chat")
|
|
2491
|
+
print(f" [log] model={self.model} messages={len(messages)} options={opts}")
|
|
2439
2492
|
with requests.post(
|
|
2440
2493
|
f"{self.base_url}/api/chat",
|
|
2441
2494
|
json={"model": self.model, "messages": messages, "stream": True,
|
|
@@ -2494,6 +2547,13 @@ class CoderCLI:
|
|
|
2494
2547
|
return None # sentinel: interrupted (vs "" which means empty reply)
|
|
2495
2548
|
except requests.exceptions.RequestException as e:
|
|
2496
2549
|
print(f"\nerror: {e}")
|
|
2550
|
+
if hasattr(e, "response") and e.response is not None:
|
|
2551
|
+
body = e.response.text.strip()
|
|
2552
|
+
if body:
|
|
2553
|
+
print(f" detail: {body[:500]}")
|
|
2554
|
+
if self.log_requests:
|
|
2555
|
+
print(f" [log] status: {e.response.status_code}")
|
|
2556
|
+
print(f" [log] headers: {dict(e.response.headers)}")
|
|
2497
2557
|
return ""
|
|
2498
2558
|
print()
|
|
2499
2559
|
reply = "".join(chunks)
|
|
@@ -2706,6 +2766,8 @@ class CoderCLI:
|
|
|
2706
2766
|
if self._run_hook("before_patch", _ha):
|
|
2707
2767
|
self._cmd_patch(user_input)
|
|
2708
2768
|
self._run_hook("after_patch", _ha)
|
|
2769
|
+
elif user_input.startswith("/fim"):
|
|
2770
|
+
self._cmd_fill(user_input)
|
|
2709
2771
|
elif user_input.startswith("/fix"):
|
|
2710
2772
|
_ha = self._extract_hook_args(user_input)
|
|
2711
2773
|
if self._run_hook("before_fix", _ha):
|
|
@@ -2882,6 +2944,8 @@ advanced_tools =
|
|
|
2882
2944
|
print(f" num_ctx = {self.num_ctx}")
|
|
2883
2945
|
print(f" think_exclude = {not self.think_in_ctx} (strip <think> blocks from context)")
|
|
2884
2946
|
print(f" think_show = {self.think_show} (show <think> blocks in terminal)")
|
|
2947
|
+
print(f" log = {self.log_requests} (print request body + error detail)")
|
|
2948
|
+
print(f" run_timeout = {self.params.get('run_timeout', 30)}s (0 = no timeout, for /run commands)")
|
|
2885
2949
|
print(f" ask_limit = {self.params.get('ask_limit', ASK_RESULT_LIMIT_CHARS)} (chars, /ask truncation limit)")
|
|
2886
2950
|
print(f" ask_show = {self.params.get('ask_show', ASK_RESULT_SHOW_CHARS)} (chars shown when truncated)")
|
|
2887
2951
|
model_params = {k: v for k, v in self.params.items() if k not in ("ask_limit", "ask_show")}
|
|
@@ -2927,6 +2991,10 @@ advanced_tools =
|
|
|
2927
2991
|
self.think_show = bool(val)
|
|
2928
2992
|
_ok(f"[param] think_show = {self.think_show}")
|
|
2929
2993
|
return
|
|
2994
|
+
if key == "log":
|
|
2995
|
+
self.log_requests = bool(val)
|
|
2996
|
+
_ok(f"[param] log = {self.log_requests}")
|
|
2997
|
+
return
|
|
2930
2998
|
self.params[key] = val
|
|
2931
2999
|
_ok(f"[param] {key} = {val}")
|
|
2932
3000
|
|
|
@@ -4061,7 +4129,7 @@ advanced_tools =
|
|
|
4061
4129
|
return
|
|
4062
4130
|
try:
|
|
4063
4131
|
current_text, _ = read_file(path, lineno, lineno)
|
|
4064
|
-
current_text = current_text.split(":", 1)[1].rstrip("\n") if ":" in current_text else current_text.rstrip()
|
|
4132
|
+
current_text = current_text.split(":", 1)[1][1:].rstrip("\n") if ":" in current_text else current_text.rstrip()
|
|
4065
4133
|
print(f" current [{lineno}]: {current_text}")
|
|
4066
4134
|
print(f" new [{lineno}]: {new_content}")
|
|
4067
4135
|
except (FileNotFoundError, OSError):
|
|
@@ -4075,6 +4143,95 @@ advanced_tools =
|
|
|
4075
4143
|
else:
|
|
4076
4144
|
print("[skipped]")
|
|
4077
4145
|
|
|
4146
|
+
def _cmd_fill(self, user_input: str):
|
|
4147
|
+
parts = user_input[4:].strip().split(None, 2)
|
|
4148
|
+
path = parts[0] if parts else ""
|
|
4149
|
+
start = end = None
|
|
4150
|
+
hint = ""
|
|
4151
|
+
if not path:
|
|
4152
|
+
print("usage: /fim <file> <line or start-end> [-w N] [hint]")
|
|
4153
|
+
return
|
|
4154
|
+
if len(parts) >= 2:
|
|
4155
|
+
m = re.match(r'^(\d+)(?:-(\d+))?$', parts[1])
|
|
4156
|
+
if m:
|
|
4157
|
+
start = int(m.group(1))
|
|
4158
|
+
end = int(m.group(2)) if m.group(2) else start
|
|
4159
|
+
hint = parts[2] if len(parts) >= 3 else ""
|
|
4160
|
+
else:
|
|
4161
|
+
hint = " ".join(parts[1:])
|
|
4162
|
+
if start is None and not hint:
|
|
4163
|
+
print("usage: /fim <file> [line or start-end] [-w N] [hint]")
|
|
4164
|
+
return
|
|
4165
|
+
# extract -w <window> from hint
|
|
4166
|
+
window = None
|
|
4167
|
+
wm = re.search(r'(?:^|\s)-w\s+(\d+)', hint)
|
|
4168
|
+
if wm:
|
|
4169
|
+
window = int(wm.group(1))
|
|
4170
|
+
hint = (hint[:wm.start()] + hint[wm.end():]).strip()
|
|
4171
|
+
try:
|
|
4172
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
4173
|
+
file_lines = f.readlines()
|
|
4174
|
+
except (FileNotFoundError, OSError) as e:
|
|
4175
|
+
_err(e)
|
|
4176
|
+
return
|
|
4177
|
+
total = len(file_lines)
|
|
4178
|
+
if start is not None and (start < 1 or end > total):
|
|
4179
|
+
_err(f"line {start}-{end} out of range (file has {total} lines)")
|
|
4180
|
+
return
|
|
4181
|
+
# compute slice for windowed mode (only when line range is given)
|
|
4182
|
+
if start is not None and window is not None:
|
|
4183
|
+
w_start = max(0, start - 1 - window) # 0-indexed inclusive
|
|
4184
|
+
w_end = min(total, end + window) # 0-indexed exclusive
|
|
4185
|
+
slice_lines = file_lines[w_start:w_end]
|
|
4186
|
+
rel_start = start - w_start # 1-indexed within slice
|
|
4187
|
+
rel_end = end - w_start
|
|
4188
|
+
else:
|
|
4189
|
+
slice_lines = file_lines
|
|
4190
|
+
rel_start, rel_end = start, end
|
|
4191
|
+
w_start, w_end = 0, total
|
|
4192
|
+
if hint:
|
|
4193
|
+
print(f"hint: {hint}")
|
|
4194
|
+
if window is not None:
|
|
4195
|
+
print(f"[fim] window: lines {w_start+1}–{w_end} of {total}")
|
|
4196
|
+
self._sep("AI")
|
|
4197
|
+
def on_chunk(c):
|
|
4198
|
+
sys.stdout.write(c)
|
|
4199
|
+
sys.stdout.flush()
|
|
4200
|
+
try:
|
|
4201
|
+
raw = ai_fill(self.base_url, self.model, slice_lines, rel_start, rel_end, hint, on_chunk, self.provider)
|
|
4202
|
+
except KeyboardInterrupt:
|
|
4203
|
+
print("\n[interrupted]")
|
|
4204
|
+
return
|
|
4205
|
+
except requests.exceptions.RequestException as e:
|
|
4206
|
+
print(f"\nerror: {e}")
|
|
4207
|
+
if hasattr(e, "response") and e.response is not None:
|
|
4208
|
+
body = e.response.text.strip()
|
|
4209
|
+
if body:
|
|
4210
|
+
print(f" detail: {body[:500]}")
|
|
4211
|
+
return
|
|
4212
|
+
print()
|
|
4213
|
+
m = re.search(r'```(?:\w+)?\n(.*?)\n```', raw, re.DOTALL)
|
|
4214
|
+
new_content = m.group(1) if m else raw.strip()
|
|
4215
|
+
new_slice = [l if l.endswith('\n') else l + '\n' for l in new_content.splitlines()]
|
|
4216
|
+
# reconstruct full file: unchanged prefix + new slice + unchanged suffix
|
|
4217
|
+
full_new = file_lines[:w_start] + new_slice + file_lines[w_end:]
|
|
4218
|
+
diff = list(difflib.unified_diff(file_lines, full_new, fromfile=path, tofile=path + " (fixed)", lineterm=""))
|
|
4219
|
+
if not diff:
|
|
4220
|
+
print("[fim] no changes detected — try a different hint or model")
|
|
4221
|
+
return
|
|
4222
|
+
for dline in diff:
|
|
4223
|
+
print(_cdiff(dline))
|
|
4224
|
+
if self._confirm(" apply? [Y/n]:"):
|
|
4225
|
+
try:
|
|
4226
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
4227
|
+
f.writelines(full_new)
|
|
4228
|
+
changed = sum(1 for d in diff if d.startswith('+') and not d.startswith('+++'))
|
|
4229
|
+
print(f"[{changed} line(s) updated in {path}]")
|
|
4230
|
+
except OSError as e:
|
|
4231
|
+
_err(e)
|
|
4232
|
+
else:
|
|
4233
|
+
print("[skipped]")
|
|
4234
|
+
|
|
4078
4235
|
# ── hook support ──────────────────────────────────────────────────────────
|
|
4079
4236
|
|
|
4080
4237
|
def _extract_hook_args(self, user_input: str) -> dict:
|
|
@@ -4303,7 +4460,7 @@ advanced_tools =
|
|
|
4303
4460
|
if search_text is None:
|
|
4304
4461
|
print("could not parse SEARCH/REPLACE block — try a more capable model")
|
|
4305
4462
|
return
|
|
4306
|
-
if search_text
|
|
4463
|
+
if search_text == replace_text:
|
|
4307
4464
|
_warn("[patch] SEARCH and REPLACE are identical — model included the new code in both blocks (no-op)")
|
|
4308
4465
|
return
|
|
4309
4466
|
try:
|
|
@@ -4454,9 +4611,11 @@ advanced_tools =
|
|
|
4454
4611
|
|
|
4455
4612
|
def _cmd_run(self, shell_cmd: str):
|
|
4456
4613
|
print(f"$ {shell_cmd}")
|
|
4614
|
+
run_timeout = self.params.get("run_timeout", 30)
|
|
4457
4615
|
try:
|
|
4458
4616
|
proc = subprocess.run(
|
|
4459
|
-
shell_cmd, shell=True, capture_output=True,
|
|
4617
|
+
shell_cmd, shell=True, capture_output=True,
|
|
4618
|
+
timeout=run_timeout if run_timeout else None,
|
|
4460
4619
|
encoding="utf-8", errors="replace",
|
|
4461
4620
|
)
|
|
4462
4621
|
output = proc.stdout + proc.stderr
|
|
@@ -7646,6 +7805,7 @@ Config stored in ~/.1bcoder/translate.json
|
|
|
7646
7805
|
print(" /map find \\!term — exclude block if any child contains term")
|
|
7647
7806
|
print(" /map find -term — show ONLY child lines containing term")
|
|
7648
7807
|
print(" /map find -!term — hide child lines containing term")
|
|
7808
|
+
print(" /map find +term — like -term but also hides files with no matching children")
|
|
7649
7809
|
print(" combine freely: auth \\register !mock -!deprecated -y -d 2")
|
|
7650
7810
|
print(" /map trace <identifier> [-d N] [-y] — follow call chain backwards from identifier")
|
|
7651
7811
|
print(" /map diff — diff map.txt vs map.prev.txt (no re-index)")
|
|
@@ -8275,13 +8435,7 @@ Config stored in ~/.1bcoder/translate.json
|
|
|
8275
8435
|
if template is None:
|
|
8276
8436
|
return user_input
|
|
8277
8437
|
if "{{args}}" in template:
|
|
8278
|
-
|
|
8279
|
-
# quoted segments and keywords like file: / plan: intact.
|
|
8280
|
-
flags = re.findall(r'--\S+', args)
|
|
8281
|
-
text = re.sub(r'\s*--\S+', '', args).strip()
|
|
8282
|
-
expanded = template.replace("{{args}}", text)
|
|
8283
|
-
if flags:
|
|
8284
|
-
expanded = expanded + " " + " ".join(flags)
|
|
8438
|
+
expanded = template.replace("{{args}}", args)
|
|
8285
8439
|
else:
|
|
8286
8440
|
expanded = (template + (" " + args if args else "")).strip()
|
|
8287
8441
|
return self._expand_alias(expanded, depth + 1)
|
|
@@ -22,6 +22,7 @@ Filter token syntax for find:
|
|
|
22
22
|
\\!term exclude entire block if any child contains term
|
|
23
23
|
-term show ONLY child lines containing term
|
|
24
24
|
-!term hide child lines containing term
|
|
25
|
+
+term show ONLY child lines containing term AND hide file if none match
|
|
25
26
|
|
|
26
27
|
(no tokens → print full map)
|
|
27
28
|
|
|
@@ -154,13 +155,14 @@ def find_map(map_path: str, query: str) -> tuple:
|
|
|
154
155
|
with open(map_path, encoding='utf-8') as f:
|
|
155
156
|
content = f.read()
|
|
156
157
|
|
|
157
|
-
tokens
|
|
158
|
-
pos_file
|
|
159
|
-
neg_file
|
|
160
|
-
pos_child
|
|
161
|
-
neg_block
|
|
162
|
-
show_lines
|
|
163
|
-
hide_lines
|
|
158
|
+
tokens = query.split()
|
|
159
|
+
pos_file = [] # term — filename must contain
|
|
160
|
+
neg_file = [] # !term — filename must NOT contain
|
|
161
|
+
pos_child = [] # \term — include block if any child line contains (all terms same line)
|
|
162
|
+
neg_block = [] # \!term — exclude block if any child line contains
|
|
163
|
+
show_lines = [] # -term — show ONLY child lines containing term (keep file even if empty)
|
|
164
|
+
hide_lines = [] # -!term — hide child lines containing term
|
|
165
|
+
must_show_lines = [] # +term — show ONLY child lines containing term AND hide file if none match
|
|
164
166
|
|
|
165
167
|
for t in tokens:
|
|
166
168
|
if t.startswith('\\!') and len(t) > 2:
|
|
@@ -171,13 +173,15 @@ def find_map(map_path: str, query: str) -> tuple:
|
|
|
171
173
|
hide_lines.append(t[2:].lower())
|
|
172
174
|
elif t.startswith('-') and len(t) > 1:
|
|
173
175
|
show_lines.append(t[1:].lower())
|
|
176
|
+
elif t.startswith('+') and len(t) > 1:
|
|
177
|
+
must_show_lines.append(t[1:].lower())
|
|
174
178
|
elif t.startswith('!') and len(t) > 1:
|
|
175
179
|
neg_file.append(t[1:].lower())
|
|
176
180
|
else:
|
|
177
181
|
pos_file.append(t.lower())
|
|
178
182
|
|
|
179
183
|
# no criteria → return full map
|
|
180
|
-
if not any([pos_file, neg_file, pos_child, neg_block, show_lines, hide_lines]):
|
|
184
|
+
if not any([pos_file, neg_file, pos_child, neg_block, show_lines, hide_lines, must_show_lines]):
|
|
181
185
|
return [], content
|
|
182
186
|
|
|
183
187
|
blocks = re.split(r'\n(?=\S)', content)
|
|
@@ -201,6 +205,11 @@ def find_map(map_path: str, query: str) -> tuple:
|
|
|
201
205
|
if show_lines:
|
|
202
206
|
child_lines = [l for l in child_lines
|
|
203
207
|
if any(t in l.lower() for t in show_lines)]
|
|
208
|
+
if must_show_lines:
|
|
209
|
+
child_lines = [l for l in child_lines
|
|
210
|
+
if any(t in l.lower() for t in must_show_lines)]
|
|
211
|
+
if not child_lines:
|
|
212
|
+
return None
|
|
204
213
|
if hide_lines:
|
|
205
214
|
child_lines = [l for l in child_lines
|
|
206
215
|
if not any(t in l.lower() for t in hide_lines)]
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "1bcoder"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.11"
|
|
8
8
|
description = "AI coding assistant agent for 1B–7B local models (Ollama, LMStudio, llama.cpp). Terminal REPL with file editing, project map, agents, scripts, and parallel multi-model queries."
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
readme = {file = "README.md", content-type = "text/markdown"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/flows/__pycache__/commit_message.cpython-311.pyc
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/personal/content/create-regular-content.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{1bcoder-0.1.10 → 1bcoder-0.1.11}/_bcoder_data/scripts/remote/create-content-on-remote-server.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|