1bcoder 0.1.8__tar.gz → 0.1.10__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.8 → 1bcoder-0.1.10}/1bcoder.egg-info/PKG-INFO +31 -4
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/PKG-INFO +31 -4
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/README.md +30 -3
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/aliases.txt +4 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/chat.py +112 -10
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/map_index.py +7 -4
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/map_query.py +68 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/pyproject.toml +1 -1
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/1bcoder.egg-info/SOURCES.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/1bcoder.egg-info/dependency_links.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/1bcoder.egg-info/entry_points.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/1bcoder.egg-info/requires.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/1bcoder.egg-info/top_level.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/LICENSE +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/__init__.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/advance.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/ask.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/compact.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/concepts.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/fill.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/planning.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/scan.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/sqlite.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/agents/websearch.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/doc/FLOWS.md +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/doc/MCP.md +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/doc/OLLAMA_SERVER_PARAM.md +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/doc/PARAM.md +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/doc/PROC.md +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/doc/TRANSLATE.md +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/flows/__pycache__/commit_message.cpython-311.pyc +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/flows/commit_message.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/flows/grounding.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/flows/py_error_trace.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/flows/simargl_files.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/flows/webask.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/map.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/action-required.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/add-save.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/assist.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/collect-files.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/ctx_cut.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/extract-code.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/extract-files.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/extract-list.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/grounding-check.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/md.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/mdx.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/pattern-gate.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/regexp-extract.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/rude_words.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/scan-save.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/secret_check.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/sql_readonly_guard.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/proc/tempctx-cut.py +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/profiles.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/prompts/analysis.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/prompts/sumarise.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/prompts.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/AddFunction.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/AskProject.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/CheckRequirements.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/DockerMySQL.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/DockerNginx.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/DockerPython.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/DockerStack.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/DuckDuckGoInstant.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/EnvTemplate.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/Explain.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/ExploreProjectStructure.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/GitIgnorePython.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/MySQLDump.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/NewScript.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/PipFreeze.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/PyPI.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/Refactor.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/RunAndFix.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/SQLiteSchema.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/Translate.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/WikiPage.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/WikiSearch.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/auto-bkup.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/edit-control.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/parallel_call.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/personal/content/create-regular-content.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/personal/content/plan.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/personal/test/collect-data-from-test-environment.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/plan.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/remote/create-content-on-remote-server.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/set_ctx.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/simargl-cli_index_files.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/simargl-cli_index_units.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/simargl-cli_search.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/team-map-worker.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/team-search-worker.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/team-summarize.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/team-tree-worker.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/scripts/test.txt +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/_bcoder_data/teams/code-analysis.yaml +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/setup.cfg +0 -0
- {1bcoder-0.1.8 → 1bcoder-0.1.10}/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.10
|
|
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
|
|
@@ -59,7 +59,7 @@ Key design decisions:
|
|
|
59
59
|
- **Short agent system prompts, at most 5 tools per agent, one function per agent** — `ask`, `edit`, `fill`, `scan`, `compact`. Not universal agents with bloated skill sets.
|
|
60
60
|
- **Tolerant of long and malformed output** — post-processing is automatic; the programmer does not teach the model JSON syntax.
|
|
61
61
|
- **`/parallel`** — send the same context to several models simultaneously and combine results; a 0.5b and a 1b model working together often outperform either alone; designed to coordinate small models running on multiple machines or phones.
|
|
62
|
-
- **`/map`** — project structure index with structural diff; lets the model navigate a codebase without loading it into context.
|
|
62
|
+
- **`/map`** — project structure index with structural diff and keyword grounding; lets the model navigate a codebase without loading it into context. Keyword extract supports three modes: exact, like (`%token%`), and fuzzy (subword); `-o` resolves each keyword to the files it appears in.
|
|
63
63
|
- **`/ctx`** — surgical context management: savepoints, selective compaction, named context library, multi-turn rollback. Small models cannot afford wasted tokens.
|
|
64
64
|
- **`/scan`** — reads any large file chunk by chunk and builds a themed summary without overflowing context.
|
|
65
65
|
- **`/proc`** — parameterized command scripts for repeatable preparation workflows.
|
|
@@ -538,8 +538,8 @@ The map command scans your project with language-agnostic regex, extracts defini
|
|
|
538
538
|
/map trace <start> <end> [-y] — shortest dependency path between two points
|
|
539
539
|
/map idiff [path] [depth] — re-index then show diff vs previous snapshot
|
|
540
540
|
/map diff — show diff without re-indexing (safe to repeat)
|
|
541
|
-
/map keyword index
|
|
542
|
-
/map keyword extract <text> [-f] [-a] [-n] [-c] — extract real identifiers from keyword.txt matching text/file
|
|
541
|
+
/map keyword index — build keyword vocabulary from map.txt
|
|
542
|
+
/map keyword extract <text> [-f] [-l] [-a] [-s] [-n] [-c] [-o] — extract real identifiers from keyword.txt matching text/file
|
|
543
543
|
```
|
|
544
544
|
|
|
545
545
|
**Partial / incremental indexing** — for large codebases where a full re-scan is slow:
|
|
@@ -583,6 +583,33 @@ This lets you re-index a changed module in seconds instead of hours.
|
|
|
583
583
|
/map find models -d 2 — filenames + defines/vars only
|
|
584
584
|
```
|
|
585
585
|
|
|
586
|
+
**`/map keyword`** — two-step identifier grounding:
|
|
587
|
+
|
|
588
|
+
```
|
|
589
|
+
/map keyword index — scan map.txt → .1bcoder/keyword.txt (word, count, line refs)
|
|
590
|
+
/map keyword extract "fix rule search" -l -o — find identifiers, show which files they're in
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
Extract flags:
|
|
594
|
+
|
|
595
|
+
| Flag | Mode | Effect |
|
|
596
|
+
|---|---|---|
|
|
597
|
+
| *(none)* | exact | query word must exactly match a keyword |
|
|
598
|
+
| `-f` | fuzzy | splits camelCase/snake_case into subwords; matches if all query subwords (≥5 chars) appear in the identifier |
|
|
599
|
+
| `-l` | like | substring match: any keyword containing the token (`%token%`) |
|
|
600
|
+
| `-n` | — | show frequency count: `RuleIndex(25)` |
|
|
601
|
+
| `-s` | — | sort by frequency descending |
|
|
602
|
+
| `-a` | — | sort alphabetically |
|
|
603
|
+
| `-c` | — | comma-separated output (default: one per line) |
|
|
604
|
+
| `-o` | — | show origin files: `parameter_rule -> lib/cop/rule.rb, config/default.yml` |
|
|
605
|
+
|
|
606
|
+
```
|
|
607
|
+
/map keyword extract "add validation rule" -l -o
|
|
608
|
+
# parameter_rule -> lib/rubocop/cop/style/rule.rb, config/default.yml
|
|
609
|
+
# cop_rule -> lib/rubocop/cop/base.rb
|
|
610
|
+
# load_rules -> lib/rubocop/config_loader.rb
|
|
611
|
+
```
|
|
612
|
+
|
|
586
613
|
**`/map trace`** — three modes:
|
|
587
614
|
|
|
588
615
|
**1. Backwards BFS** (who depends on this?):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: 1bcoder
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
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
|
|
@@ -59,7 +59,7 @@ Key design decisions:
|
|
|
59
59
|
- **Short agent system prompts, at most 5 tools per agent, one function per agent** — `ask`, `edit`, `fill`, `scan`, `compact`. Not universal agents with bloated skill sets.
|
|
60
60
|
- **Tolerant of long and malformed output** — post-processing is automatic; the programmer does not teach the model JSON syntax.
|
|
61
61
|
- **`/parallel`** — send the same context to several models simultaneously and combine results; a 0.5b and a 1b model working together often outperform either alone; designed to coordinate small models running on multiple machines or phones.
|
|
62
|
-
- **`/map`** — project structure index with structural diff; lets the model navigate a codebase without loading it into context.
|
|
62
|
+
- **`/map`** — project structure index with structural diff and keyword grounding; lets the model navigate a codebase without loading it into context. Keyword extract supports three modes: exact, like (`%token%`), and fuzzy (subword); `-o` resolves each keyword to the files it appears in.
|
|
63
63
|
- **`/ctx`** — surgical context management: savepoints, selective compaction, named context library, multi-turn rollback. Small models cannot afford wasted tokens.
|
|
64
64
|
- **`/scan`** — reads any large file chunk by chunk and builds a themed summary without overflowing context.
|
|
65
65
|
- **`/proc`** — parameterized command scripts for repeatable preparation workflows.
|
|
@@ -538,8 +538,8 @@ The map command scans your project with language-agnostic regex, extracts defini
|
|
|
538
538
|
/map trace <start> <end> [-y] — shortest dependency path between two points
|
|
539
539
|
/map idiff [path] [depth] — re-index then show diff vs previous snapshot
|
|
540
540
|
/map diff — show diff without re-indexing (safe to repeat)
|
|
541
|
-
/map keyword index
|
|
542
|
-
/map keyword extract <text> [-f] [-a] [-n] [-c] — extract real identifiers from keyword.txt matching text/file
|
|
541
|
+
/map keyword index — build keyword vocabulary from map.txt
|
|
542
|
+
/map keyword extract <text> [-f] [-l] [-a] [-s] [-n] [-c] [-o] — extract real identifiers from keyword.txt matching text/file
|
|
543
543
|
```
|
|
544
544
|
|
|
545
545
|
**Partial / incremental indexing** — for large codebases where a full re-scan is slow:
|
|
@@ -583,6 +583,33 @@ This lets you re-index a changed module in seconds instead of hours.
|
|
|
583
583
|
/map find models -d 2 — filenames + defines/vars only
|
|
584
584
|
```
|
|
585
585
|
|
|
586
|
+
**`/map keyword`** — two-step identifier grounding:
|
|
587
|
+
|
|
588
|
+
```
|
|
589
|
+
/map keyword index — scan map.txt → .1bcoder/keyword.txt (word, count, line refs)
|
|
590
|
+
/map keyword extract "fix rule search" -l -o — find identifiers, show which files they're in
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
Extract flags:
|
|
594
|
+
|
|
595
|
+
| Flag | Mode | Effect |
|
|
596
|
+
|---|---|---|
|
|
597
|
+
| *(none)* | exact | query word must exactly match a keyword |
|
|
598
|
+
| `-f` | fuzzy | splits camelCase/snake_case into subwords; matches if all query subwords (≥5 chars) appear in the identifier |
|
|
599
|
+
| `-l` | like | substring match: any keyword containing the token (`%token%`) |
|
|
600
|
+
| `-n` | — | show frequency count: `RuleIndex(25)` |
|
|
601
|
+
| `-s` | — | sort by frequency descending |
|
|
602
|
+
| `-a` | — | sort alphabetically |
|
|
603
|
+
| `-c` | — | comma-separated output (default: one per line) |
|
|
604
|
+
| `-o` | — | show origin files: `parameter_rule -> lib/cop/rule.rb, config/default.yml` |
|
|
605
|
+
|
|
606
|
+
```
|
|
607
|
+
/map keyword extract "add validation rule" -l -o
|
|
608
|
+
# parameter_rule -> lib/rubocop/cop/style/rule.rb, config/default.yml
|
|
609
|
+
# cop_rule -> lib/rubocop/cop/base.rb
|
|
610
|
+
# load_rules -> lib/rubocop/config_loader.rb
|
|
611
|
+
```
|
|
612
|
+
|
|
586
613
|
**`/map trace`** — three modes:
|
|
587
614
|
|
|
588
615
|
**1. Backwards BFS** (who depends on this?):
|
|
@@ -44,7 +44,7 @@ Key design decisions:
|
|
|
44
44
|
- **Short agent system prompts, at most 5 tools per agent, one function per agent** — `ask`, `edit`, `fill`, `scan`, `compact`. Not universal agents with bloated skill sets.
|
|
45
45
|
- **Tolerant of long and malformed output** — post-processing is automatic; the programmer does not teach the model JSON syntax.
|
|
46
46
|
- **`/parallel`** — send the same context to several models simultaneously and combine results; a 0.5b and a 1b model working together often outperform either alone; designed to coordinate small models running on multiple machines or phones.
|
|
47
|
-
- **`/map`** — project structure index with structural diff; lets the model navigate a codebase without loading it into context.
|
|
47
|
+
- **`/map`** — project structure index with structural diff and keyword grounding; lets the model navigate a codebase without loading it into context. Keyword extract supports three modes: exact, like (`%token%`), and fuzzy (subword); `-o` resolves each keyword to the files it appears in.
|
|
48
48
|
- **`/ctx`** — surgical context management: savepoints, selective compaction, named context library, multi-turn rollback. Small models cannot afford wasted tokens.
|
|
49
49
|
- **`/scan`** — reads any large file chunk by chunk and builds a themed summary without overflowing context.
|
|
50
50
|
- **`/proc`** — parameterized command scripts for repeatable preparation workflows.
|
|
@@ -523,8 +523,8 @@ The map command scans your project with language-agnostic regex, extracts defini
|
|
|
523
523
|
/map trace <start> <end> [-y] — shortest dependency path between two points
|
|
524
524
|
/map idiff [path] [depth] — re-index then show diff vs previous snapshot
|
|
525
525
|
/map diff — show diff without re-indexing (safe to repeat)
|
|
526
|
-
/map keyword index
|
|
527
|
-
/map keyword extract <text> [-f] [-a] [-n] [-c] — extract real identifiers from keyword.txt matching text/file
|
|
526
|
+
/map keyword index — build keyword vocabulary from map.txt
|
|
527
|
+
/map keyword extract <text> [-f] [-l] [-a] [-s] [-n] [-c] [-o] — extract real identifiers from keyword.txt matching text/file
|
|
528
528
|
```
|
|
529
529
|
|
|
530
530
|
**Partial / incremental indexing** — for large codebases where a full re-scan is slow:
|
|
@@ -568,6 +568,33 @@ This lets you re-index a changed module in seconds instead of hours.
|
|
|
568
568
|
/map find models -d 2 — filenames + defines/vars only
|
|
569
569
|
```
|
|
570
570
|
|
|
571
|
+
**`/map keyword`** — two-step identifier grounding:
|
|
572
|
+
|
|
573
|
+
```
|
|
574
|
+
/map keyword index — scan map.txt → .1bcoder/keyword.txt (word, count, line refs)
|
|
575
|
+
/map keyword extract "fix rule search" -l -o — find identifiers, show which files they're in
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
Extract flags:
|
|
579
|
+
|
|
580
|
+
| Flag | Mode | Effect |
|
|
581
|
+
|---|---|---|
|
|
582
|
+
| *(none)* | exact | query word must exactly match a keyword |
|
|
583
|
+
| `-f` | fuzzy | splits camelCase/snake_case into subwords; matches if all query subwords (≥5 chars) appear in the identifier |
|
|
584
|
+
| `-l` | like | substring match: any keyword containing the token (`%token%`) |
|
|
585
|
+
| `-n` | — | show frequency count: `RuleIndex(25)` |
|
|
586
|
+
| `-s` | — | sort by frequency descending |
|
|
587
|
+
| `-a` | — | sort alphabetically |
|
|
588
|
+
| `-c` | — | comma-separated output (default: one per line) |
|
|
589
|
+
| `-o` | — | show origin files: `parameter_rule -> lib/cop/rule.rb, config/default.yml` |
|
|
590
|
+
|
|
591
|
+
```
|
|
592
|
+
/map keyword extract "add validation rule" -l -o
|
|
593
|
+
# parameter_rule -> lib/rubocop/cop/style/rule.rb, config/default.yml
|
|
594
|
+
# cop_rule -> lib/rubocop/cop/base.rb
|
|
595
|
+
# load_rules -> lib/rubocop/config_loader.rb
|
|
596
|
+
```
|
|
597
|
+
|
|
571
598
|
**`/map trace`** — three modes:
|
|
572
599
|
|
|
573
600
|
**1. Backwards BFS** (who depends on this?):
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
/compact = /agent compact {{args}}
|
|
12
12
|
/websearch = /agent websearch {{args}}
|
|
13
13
|
/webask = /flow webask {{args}}
|
|
14
|
+
/simargl = /run simargl {{args}}
|
|
15
|
+
/sim = /run simargl {{args}}
|
|
16
|
+
/svitovyd = /run svitovyd {{args}}
|
|
17
|
+
/svi = /run svitovyd {{args}}
|
|
14
18
|
|
|
15
19
|
/small = /parallel {{args}} profile: small
|
|
16
20
|
/explain = /parallel {{args}} profile: explain
|
|
@@ -916,7 +916,7 @@ Output capture operators (work with any command — LLM reply, tool, proc):
|
|
|
916
916
|
CSV format: word, count, semicolon-separated list of line numbers in map.txt.
|
|
917
917
|
Sorted alphabetically. Run once after /map index (or whenever map changes).
|
|
918
918
|
e.g. /map keyword index
|
|
919
|
-
/map keyword extract <text or file> [-a] [-f] [-n] [-c]
|
|
919
|
+
/map keyword extract <text or file> [-a] [-s] [-f] [-l] [-n] [-c] [-o]
|
|
920
920
|
Extract real identifiers from keyword.txt matching words in the given text or file.
|
|
921
921
|
Output is always real identifiers from keyword.txt — never synthetic splits.
|
|
922
922
|
Default (exact): query word must exactly match a keyword.txt entry.
|
|
@@ -928,16 +928,20 @@ Output capture operators (work with any command — LLM reply, tool, proc):
|
|
|
928
928
|
"RuleIndex" → matches RuleIndex only (needs both 'rule' AND 'index')
|
|
929
929
|
"coverage" → matches CoverageMetric, LineCoverage, BranchCoverage
|
|
930
930
|
"RuleIndex" → does NOT match Rule (missing 'index') or Index (missing 'rule')
|
|
931
|
+
-l like match (%token%): any keyword containing the query token as substring
|
|
932
|
+
"rule" → RuleIndex, rule_validator, parseRule, getRuleSet
|
|
931
933
|
-a alphabetical order
|
|
932
934
|
-s sort by codebase count descending (most frequent first)
|
|
933
935
|
-n show codebase count next to each word: RuleIndex(25) RuleName(12)
|
|
934
936
|
(-n implies -s)
|
|
935
937
|
-c comma-separated output instead of one per line
|
|
938
|
+
-o show origin: which files each keyword appears in: keyword -> file1, file2
|
|
936
939
|
e.g. /map keyword extract notes.txt
|
|
937
940
|
/map keyword extract notes.txt -f
|
|
941
|
+
/map keyword extract notes.txt -l
|
|
938
942
|
/map keyword extract notes.txt -f -n -c
|
|
939
943
|
/map keyword extract "add isbn field to the Book class" -f -a
|
|
940
|
-
/map keyword extract "fix rule search" -
|
|
944
|
+
/map keyword extract "fix rule search" -l -o
|
|
941
945
|
|
|
942
946
|
/hook before|after <cmd> <script>
|
|
943
947
|
Run a script before or after a command (edit, patch, fix, insert).
|
|
@@ -1175,8 +1179,11 @@ def _fmt_ctx(n: int) -> str:
|
|
|
1175
1179
|
|
|
1176
1180
|
|
|
1177
1181
|
def read_file(path, start=None, end=None, line_numbers=True):
|
|
1178
|
-
|
|
1179
|
-
|
|
1182
|
+
try:
|
|
1183
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
1184
|
+
lines = f.readlines()
|
|
1185
|
+
except UnicodeDecodeError:
|
|
1186
|
+
raise ValueError(f"[read] {path}: binary file, cannot read as text")
|
|
1180
1187
|
total = len(lines)
|
|
1181
1188
|
if start is not None:
|
|
1182
1189
|
start = max(1, start)
|
|
@@ -2243,6 +2250,30 @@ class CoderCLI:
|
|
|
2243
2250
|
right = right[:5]
|
|
2244
2251
|
return f"{left}:{right}" if right else left
|
|
2245
2252
|
|
|
2253
|
+
def _autosave_prompt(self) -> None:
|
|
2254
|
+
"""Ask user whether to save context; save to .1bcoder/autosave/ if confirmed."""
|
|
2255
|
+
if not self.messages:
|
|
2256
|
+
return
|
|
2257
|
+
try:
|
|
2258
|
+
ans = input("Save context before action? [Y/n] ").strip().lower()
|
|
2259
|
+
except (EOFError, KeyboardInterrupt):
|
|
2260
|
+
print()
|
|
2261
|
+
return
|
|
2262
|
+
if ans == "n":
|
|
2263
|
+
return
|
|
2264
|
+
import datetime as _dt
|
|
2265
|
+
stamp = _dt.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
|
2266
|
+
save_dir = os.path.join(
|
|
2267
|
+
BCODER_DIR if os.path.isdir(BCODER_DIR) else HOME_BCODER_DIR,
|
|
2268
|
+
"autosave"
|
|
2269
|
+
)
|
|
2270
|
+
os.makedirs(save_dir, exist_ok=True)
|
|
2271
|
+
fpath = os.path.join(save_dir, f"{stamp}.txt")
|
|
2272
|
+
with open(fpath, "w", encoding="utf-8") as f:
|
|
2273
|
+
for msg in self.messages:
|
|
2274
|
+
f.write(f"=== {msg['role']} ===\n{msg['content']}\n\n")
|
|
2275
|
+
print(f"[autosave] context saved → {fpath}")
|
|
2276
|
+
|
|
2246
2277
|
def _print_status(self) -> None:
|
|
2247
2278
|
"""Print a single status line showing model, size, quant, native ctx, and usage."""
|
|
2248
2279
|
est_tokens = sum(len(m["content"]) for m in self.messages) // 4
|
|
@@ -2253,6 +2284,7 @@ class CoderCLI:
|
|
|
2253
2284
|
parts.append(_fmt_ctx(self._meta_ctx))
|
|
2254
2285
|
meta = f" [{' '.join(parts)}]" if parts else ""
|
|
2255
2286
|
print(f"\033[2m {model_str}{meta} │ ctx {est_tokens} / {self.num_ctx} ({pct}%)\033[0m")
|
|
2287
|
+
print()
|
|
2256
2288
|
|
|
2257
2289
|
def __init__(self, base_url, model, models, provider="ollama"):
|
|
2258
2290
|
self.base_url = base_url
|
|
@@ -2350,6 +2382,8 @@ class CoderCLI:
|
|
|
2350
2382
|
) as resp:
|
|
2351
2383
|
resp.raise_for_status()
|
|
2352
2384
|
in_think = False
|
|
2385
|
+
_had_thinking = False
|
|
2386
|
+
_sep_done = False
|
|
2353
2387
|
for line in resp.iter_lines():
|
|
2354
2388
|
if not line:
|
|
2355
2389
|
continue
|
|
@@ -2367,6 +2401,7 @@ class CoderCLI:
|
|
|
2367
2401
|
reasoning = delta.get("reasoning_content") or ""
|
|
2368
2402
|
if reasoning and self.think_show:
|
|
2369
2403
|
_print(f"\033[90m{reasoning}\033[0m")
|
|
2404
|
+
_had_thinking = True
|
|
2370
2405
|
chunk = delta.get("content") or ""
|
|
2371
2406
|
if chunk:
|
|
2372
2407
|
# apply <think>...</think> state machine (same as Ollama path)
|
|
@@ -2385,6 +2420,9 @@ class CoderCLI:
|
|
|
2385
2420
|
else:
|
|
2386
2421
|
start = chunk.find('<think>')
|
|
2387
2422
|
if start == -1:
|
|
2423
|
+
if _had_thinking and not _sep_done:
|
|
2424
|
+
_print("\n")
|
|
2425
|
+
_sep_done = True
|
|
2388
2426
|
_print(chunk)
|
|
2389
2427
|
chunks.append(chunk)
|
|
2390
2428
|
chunk = ""
|
|
@@ -2393,6 +2431,7 @@ class CoderCLI:
|
|
|
2393
2431
|
_print(chunk[:start])
|
|
2394
2432
|
chunks.append(chunk[:start])
|
|
2395
2433
|
in_think = True
|
|
2434
|
+
_had_thinking = True
|
|
2396
2435
|
chunk = chunk[start + 7:]
|
|
2397
2436
|
else:
|
|
2398
2437
|
opts = {"num_ctx": self.num_ctx}
|
|
@@ -2405,6 +2444,8 @@ class CoderCLI:
|
|
|
2405
2444
|
) as resp:
|
|
2406
2445
|
resp.raise_for_status()
|
|
2407
2446
|
in_think = False
|
|
2447
|
+
_had_thinking = False
|
|
2448
|
+
_sep_done = False
|
|
2408
2449
|
for line in resp.iter_lines():
|
|
2409
2450
|
if not line:
|
|
2410
2451
|
continue
|
|
@@ -2414,6 +2455,7 @@ class CoderCLI:
|
|
|
2414
2455
|
thinking = msg.get("thinking", "")
|
|
2415
2456
|
if thinking and self.think_show:
|
|
2416
2457
|
_print(f"\033[90m{thinking}\033[0m")
|
|
2458
|
+
_had_thinking = True
|
|
2417
2459
|
chunk = msg.get("content", "")
|
|
2418
2460
|
if chunk:
|
|
2419
2461
|
# State machine: track <think>...</think> across tokens
|
|
@@ -2432,6 +2474,9 @@ class CoderCLI:
|
|
|
2432
2474
|
else:
|
|
2433
2475
|
start = chunk.find('<think>')
|
|
2434
2476
|
if start == -1:
|
|
2477
|
+
if _had_thinking and not _sep_done:
|
|
2478
|
+
_print("\n")
|
|
2479
|
+
_sep_done = True
|
|
2435
2480
|
_print(chunk)
|
|
2436
2481
|
chunks.append(chunk)
|
|
2437
2482
|
chunk = ""
|
|
@@ -2440,6 +2485,7 @@ class CoderCLI:
|
|
|
2440
2485
|
_print(chunk[:start])
|
|
2441
2486
|
chunks.append(chunk[:start])
|
|
2442
2487
|
in_think = True
|
|
2488
|
+
_had_thinking = True
|
|
2443
2489
|
chunk = chunk[start + len('<think>'):]
|
|
2444
2490
|
if data.get("done"):
|
|
2445
2491
|
break
|
|
@@ -2484,9 +2530,9 @@ class CoderCLI:
|
|
|
2484
2530
|
self._apply_config(_session_cfg)
|
|
2485
2531
|
print()
|
|
2486
2532
|
self._translate_autoload()
|
|
2533
|
+
self._print_status()
|
|
2487
2534
|
while True:
|
|
2488
2535
|
try:
|
|
2489
|
-
self._print_status()
|
|
2490
2536
|
user_input = input("> ").strip()
|
|
2491
2537
|
except (EOFError, KeyboardInterrupt):
|
|
2492
2538
|
print()
|
|
@@ -2496,6 +2542,7 @@ class CoderCLI:
|
|
|
2496
2542
|
if user_input not in self._history or (self._history and self._history[-1] != user_input):
|
|
2497
2543
|
self._history.append(user_input)
|
|
2498
2544
|
self._route(user_input)
|
|
2545
|
+
self._print_status()
|
|
2499
2546
|
if user_input.startswith("/"):
|
|
2500
2547
|
import shlex as _shlex
|
|
2501
2548
|
_args = user_input.split(None, 1)[1] if " " in user_input else ""
|
|
@@ -2569,6 +2616,7 @@ class CoderCLI:
|
|
|
2569
2616
|
return
|
|
2570
2617
|
|
|
2571
2618
|
if user_input == "/exit":
|
|
2619
|
+
self._autosave_prompt()
|
|
2572
2620
|
sys.exit(0)
|
|
2573
2621
|
elif user_input == "/about":
|
|
2574
2622
|
self._cmd_about()
|
|
@@ -2940,6 +2988,10 @@ advanced_tools =
|
|
|
2940
2988
|
print(f"[no messages found in {load_path}]")
|
|
2941
2989
|
return
|
|
2942
2990
|
self.messages.extend(loaded)
|
|
2991
|
+
last_a = next((m["content"] for m in reversed(loaded) if m["role"] == "assistant"), "")
|
|
2992
|
+
if last_a:
|
|
2993
|
+
self.last_reply = last_a
|
|
2994
|
+
self._last_output = last_a
|
|
2943
2995
|
print(f"[loaded {len(loaded)} messages from {load_path}]")
|
|
2944
2996
|
except FileNotFoundError:
|
|
2945
2997
|
print(f"file not found: {load_path}")
|
|
@@ -3086,6 +3138,7 @@ advanced_tools =
|
|
|
3086
3138
|
print("[ctx compact] failed — context unchanged")
|
|
3087
3139
|
return
|
|
3088
3140
|
|
|
3141
|
+
self._autosave_prompt()
|
|
3089
3142
|
if use_savepoint:
|
|
3090
3143
|
del self.messages[self._savepoint:]
|
|
3091
3144
|
self.messages.append({"role": "user", "content": f"[summary since savepoint]\n{summary}"})
|
|
@@ -3782,7 +3835,7 @@ advanced_tools =
|
|
|
3782
3835
|
_ok(f"context: injected {label}")
|
|
3783
3836
|
except FileNotFoundError:
|
|
3784
3837
|
print(f"file not found: {path}")
|
|
3785
|
-
except OSError as e:
|
|
3838
|
+
except (OSError, ValueError) as e:
|
|
3786
3839
|
_err(e)
|
|
3787
3840
|
|
|
3788
3841
|
def _cmd_edit(self, user_input: str):
|
|
@@ -4984,7 +5037,21 @@ advanced_tools =
|
|
|
4984
5037
|
try:
|
|
4985
5038
|
if mode == "online":
|
|
4986
5039
|
from deep_translator import GoogleTranslator as _GT
|
|
4987
|
-
|
|
5040
|
+
_MAX = 4500
|
|
5041
|
+
if len(text) <= _MAX:
|
|
5042
|
+
return _GT(source=from_lang, target=to_lang).translate(text) or text
|
|
5043
|
+
# chunk by paragraphs to stay under Google's limit
|
|
5044
|
+
_parts, _buf, _results = text.split("\n\n"), "", []
|
|
5045
|
+
for _p in _parts:
|
|
5046
|
+
if len(_buf) + len(_p) + 2 <= _MAX:
|
|
5047
|
+
_buf = (_buf + "\n\n" + _p) if _buf else _p
|
|
5048
|
+
else:
|
|
5049
|
+
if _buf:
|
|
5050
|
+
_results.append(_GT(source=from_lang, target=to_lang).translate(_buf) or _buf)
|
|
5051
|
+
_buf = _p
|
|
5052
|
+
if _buf:
|
|
5053
|
+
_results.append(_GT(source=from_lang, target=to_lang).translate(_buf) or _buf)
|
|
5054
|
+
return "\n\n".join(_results)
|
|
4988
5055
|
elif mode == "lm":
|
|
4989
5056
|
cfg = self._translate_load_cfg()
|
|
4990
5057
|
lm_timeout = int(cfg.get("lm_timeout", 120))
|
|
@@ -5567,7 +5634,10 @@ Config stored in ~/.1bcoder/translate.json
|
|
|
5567
5634
|
translated = self._translate_run(self.last_reply, "en", lang, mode=mode)
|
|
5568
5635
|
self.last_translated_reply = translated
|
|
5569
5636
|
print(f"\n{_LBLUE}─── {lang.upper()} ───{_R}")
|
|
5570
|
-
|
|
5637
|
+
if translated:
|
|
5638
|
+
print(translated)
|
|
5639
|
+
else:
|
|
5640
|
+
print("[translate] translation returned empty result — check language code or network")
|
|
5571
5641
|
return
|
|
5572
5642
|
|
|
5573
5643
|
print("usage: /translate setup [lang:uk] [mode:lm] [host:<url>] [model:<name>] [profile:<name>]")
|
|
@@ -7668,11 +7738,13 @@ Config stored in ~/.1bcoder/translate.json
|
|
|
7668
7738
|
sort_alpha = "-a" in args
|
|
7669
7739
|
sort_count = "-s" in args
|
|
7670
7740
|
fuzzy = "-f" in args
|
|
7741
|
+
like = "-l" in args
|
|
7671
7742
|
show_counts = "-n" in args
|
|
7672
7743
|
csv_out = "-c" in args
|
|
7673
|
-
|
|
7744
|
+
show_origin = "-o" in args
|
|
7745
|
+
src_tokens = [a for a in args if a not in ("-a", "-s", "-f", "-l", "-n", "-c", "-o")]
|
|
7674
7746
|
if not src_tokens:
|
|
7675
|
-
print("usage: /map keyword extract <text or file> [-a] [-s] [-f] [-n] [-c]")
|
|
7747
|
+
print("usage: /map keyword extract <text or file> [-a] [-s] [-f] [-l] [-n] [-c] [-o]")
|
|
7676
7748
|
return
|
|
7677
7749
|
# load keyword vocab: word → count
|
|
7678
7750
|
_csv.field_size_limit(10_000_000) # lines field can be large for common words
|
|
@@ -7714,6 +7786,12 @@ Config stored in ~/.1bcoder/translate.json
|
|
|
7714
7786
|
# keyword matches if ALL query subwords are present in keyword's subwords
|
|
7715
7787
|
if query_parts <= kp and kw not in seen:
|
|
7716
7788
|
seen[kw] = i
|
|
7789
|
+
elif like:
|
|
7790
|
+
for i, m in enumerate(token_re.finditer(text)):
|
|
7791
|
+
token = m.group().lower()
|
|
7792
|
+
for j, kw in enumerate(kw_freq):
|
|
7793
|
+
if token in kw.lower() and kw not in seen:
|
|
7794
|
+
seen[kw] = i * 100000 + j
|
|
7717
7795
|
else:
|
|
7718
7796
|
# default: exact identifier match
|
|
7719
7797
|
kw_set = set(kw_freq)
|
|
@@ -7730,6 +7808,30 @@ Config stored in ~/.1bcoder/translate.json
|
|
|
7730
7808
|
result = sorted(seen, key=lambda w: (-kw_freq[w], w.lower()))
|
|
7731
7809
|
else:
|
|
7732
7810
|
result = sorted(seen, key=lambda w: (seen[w], w.lower()))
|
|
7811
|
+
if show_origin:
|
|
7812
|
+
map_path = os.path.join(BCODER_DIR, "map.txt")
|
|
7813
|
+
line_to_file = map_query._build_line_to_file(map_path)
|
|
7814
|
+
# load line numbers column from keyword.txt
|
|
7815
|
+
kw_lines: dict = {}
|
|
7816
|
+
with open(kw_path, encoding="utf-8", newline="") as f:
|
|
7817
|
+
reader2 = _csv.reader(f)
|
|
7818
|
+
next(reader2, None)
|
|
7819
|
+
for row in reader2:
|
|
7820
|
+
if len(row) >= 3 and row[0] in seen:
|
|
7821
|
+
kw_lines[row[0]] = [int(x) for x in row[2].split(";") if x]
|
|
7822
|
+
lines_out = []
|
|
7823
|
+
for w in result:
|
|
7824
|
+
label = f"{w}({kw_freq[w]})" if show_counts else w
|
|
7825
|
+
files: list = []
|
|
7826
|
+
seen_files: set = set()
|
|
7827
|
+
for ln in kw_lines.get(w, []):
|
|
7828
|
+
f = line_to_file.get(ln)
|
|
7829
|
+
if f and f not in seen_files:
|
|
7830
|
+
seen_files.add(f)
|
|
7831
|
+
files.append(f)
|
|
7832
|
+
lines_out.append(f"{label} -> {', '.join(files)}" if files else label)
|
|
7833
|
+
print("\n".join(lines_out))
|
|
7834
|
+
return
|
|
7733
7835
|
if show_counts:
|
|
7734
7836
|
items = [f"{w}({kw_freq[w]})" for w in result]
|
|
7735
7837
|
else:
|
|
@@ -292,15 +292,18 @@ def build_map(root: str, depth: int = 2, map_path: str = None) -> str:
|
|
|
292
292
|
global_index[name] = rel
|
|
293
293
|
|
|
294
294
|
# ── link phase (changed files only) ──────────────────────────────────────────
|
|
295
|
+
global_set = set(global_index.keys())
|
|
295
296
|
file_links = {} # rel → { target_rel → { name → kind } }
|
|
296
297
|
for rel, text in tqdm(file_content.items(), desc="linking", unit="file", file=sys.stderr):
|
|
298
|
+
tokens_in_file = set(_WORD_RE.findall(text))
|
|
299
|
+
candidates = tokens_in_file & global_set
|
|
297
300
|
by_target = {}
|
|
298
|
-
for name
|
|
301
|
+
for name in candidates:
|
|
302
|
+
target_rel = global_index[name]
|
|
299
303
|
if target_rel == rel:
|
|
300
304
|
continue
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
by_target.setdefault(target_rel, {})[name] = kind
|
|
305
|
+
kind = classify_ref(name, text)
|
|
306
|
+
by_target.setdefault(target_rel, {})[name] = kind
|
|
304
307
|
file_links[rel] = by_target
|
|
305
308
|
|
|
306
309
|
# ── format output ────────────────────────────────────────────────────────────
|
|
@@ -538,6 +538,74 @@ def idiff_report(map_prev: str, map_curr: str) -> str:
|
|
|
538
538
|
return '\n'.join(lines)
|
|
539
539
|
|
|
540
540
|
|
|
541
|
+
# ── keywords ────────────────────────────────────────────────────────────────────
|
|
542
|
+
|
|
543
|
+
def _split_identifier(name: str) -> list:
|
|
544
|
+
"""Split camelCase / snake_case / PascalCase into lowercase subwords."""
|
|
545
|
+
parts = re.split(r'[_\-]+', name)
|
|
546
|
+
result = []
|
|
547
|
+
for part in parts:
|
|
548
|
+
if not part:
|
|
549
|
+
continue
|
|
550
|
+
s = re.sub(r'([A-Z]+)([A-Z][a-z])', r'\1_\2', part)
|
|
551
|
+
s = re.sub(r'([a-z\d])([A-Z])', r'\1_\2', s)
|
|
552
|
+
result.extend(w.lower() for w in s.split('_') if len(w) >= 2)
|
|
553
|
+
seen: dict = {}
|
|
554
|
+
for w in result:
|
|
555
|
+
seen.setdefault(w, None)
|
|
556
|
+
return list(seen)
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
def _build_line_to_file(map_path: str) -> dict:
|
|
560
|
+
"""Return {line_number: file_path} for every line in map.txt.
|
|
561
|
+
|
|
562
|
+
File ownership: nearest non-indented, non-comment line above.
|
|
563
|
+
"""
|
|
564
|
+
with open(map_path, encoding='utf-8', errors='replace') as f:
|
|
565
|
+
lines = f.readlines()
|
|
566
|
+
result = {}
|
|
567
|
+
current_file = None
|
|
568
|
+
for i, line in enumerate(lines, 1):
|
|
569
|
+
stripped = line.rstrip('\n')
|
|
570
|
+
if stripped and not stripped[0].isspace() and not stripped.startswith('#'):
|
|
571
|
+
current_file = stripped.strip()
|
|
572
|
+
if current_file:
|
|
573
|
+
result[i] = current_file
|
|
574
|
+
return result
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def keyword_to_files(map_path: str, word: str) -> list:
|
|
578
|
+
"""Return list of files where *word* appears, in order of first occurrence."""
|
|
579
|
+
import csv as _csv
|
|
580
|
+
|
|
581
|
+
kw_path = os.path.join(os.path.dirname(os.path.abspath(map_path)), 'keyword.txt')
|
|
582
|
+
if not os.path.exists(kw_path):
|
|
583
|
+
return []
|
|
584
|
+
|
|
585
|
+
line_nums = []
|
|
586
|
+
_csv.field_size_limit(10_000_000)
|
|
587
|
+
with open(kw_path, encoding='utf-8', newline='') as f:
|
|
588
|
+
reader = _csv.reader(f)
|
|
589
|
+
next(reader, None)
|
|
590
|
+
for row in reader:
|
|
591
|
+
if len(row) >= 3 and row[0] == word:
|
|
592
|
+
line_nums = [int(x) for x in row[2].split(';') if x]
|
|
593
|
+
break
|
|
594
|
+
|
|
595
|
+
if not line_nums:
|
|
596
|
+
return []
|
|
597
|
+
|
|
598
|
+
line_to_file = _build_line_to_file(map_path)
|
|
599
|
+
seen: set = set()
|
|
600
|
+
files = []
|
|
601
|
+
for ln in line_nums:
|
|
602
|
+
f = line_to_file.get(ln)
|
|
603
|
+
if f and f not in seen:
|
|
604
|
+
seen.add(f)
|
|
605
|
+
files.append(f)
|
|
606
|
+
return files
|
|
607
|
+
|
|
608
|
+
|
|
541
609
|
# ── CLI entry point ─────────────────────────────────────────────────────────────
|
|
542
610
|
|
|
543
611
|
def main():
|
|
@@ -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.10"
|
|
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
|
|
File without changes
|
{1bcoder-0.1.8 → 1bcoder-0.1.10}/_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.8 → 1bcoder-0.1.10}/_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.8 → 1bcoder-0.1.10}/_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
|