ctxora 6.2.0
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.
- package/LICENSE +21 -0
- package/README.md +441 -0
- package/README.vi.md +441 -0
- package/bin/ctxora.mjs +147 -0
- package/package.json +45 -0
- package/pyproject.toml +59 -0
- package/src/chunking/compressor.py +104 -0
- package/src/chunking/treesitter_chunker.py +240 -0
- package/src/compact/anthropic.py +98 -0
- package/src/compact/gemini.py +88 -0
- package/src/compact/handoff.py +179 -0
- package/src/compact/openai.py +318 -0
- package/src/compact/summarizer.py +186 -0
- package/src/context/assembler.py +298 -0
- package/src/context/budgeting.py +137 -0
- package/src/context/sanitizer.py +23 -0
- package/src/evaluation/__init__.py +1 -0
- package/src/evaluation/gates.py +172 -0
- package/src/evaluation/metrics.py +41 -0
- package/src/harness_context/__init__.py +5 -0
- package/src/harness_context/adapters/__init__.py +1 -0
- package/src/harness_context/adapters/clients/__init__.py +4 -0
- package/src/harness_context/adapters/clients/formatters.py +47 -0
- package/src/harness_context/adapters/clients/profiles.py +29 -0
- package/src/harness_context/adapters/ecc/__init__.py +4 -0
- package/src/harness_context/adapters/ecc/detection.py +41 -0
- package/src/harness_context/adapters/ecc/mapping.py +32 -0
- package/src/harness_context/adapters/ecc/memory_reader.py +162 -0
- package/src/harness_context/adapters/ecc/provenance.py +16 -0
- package/src/harness_context/api/__init__.py +1 -0
- package/src/harness_context/api/v2/__init__.py +12 -0
- package/src/harness_context/api/v2/contracts.py +119 -0
- package/src/harness_context/api/v2/diagnostics.py +13 -0
- package/src/harness_context/api/v2/enums.py +17 -0
- package/src/harness_context/api/v2/errors.py +32 -0
- package/src/harness_context/api/v2/models.py +4 -0
- package/src/harness_context/api/v2/requests.py +17 -0
- package/src/harness_context/api/v2/responses.py +22 -0
- package/src/harness_context/application/__init__.py +3 -0
- package/src/harness_context/application/container.py +31 -0
- package/src/harness_context/application/context_service.py +51 -0
- package/src/harness_context/application/ecc_service.py +7 -0
- package/src/harness_context/application/handoff_service.py +11 -0
- package/src/harness_context/application/memory_service.py +9 -0
- package/src/harness_context/application/protocols.py +46 -0
- package/src/harness_context/application/refresh_service.py +25 -0
- package/src/harness_context/application/retrieval_service.py +22 -0
- package/src/harness_context/application/services.py +4 -0
- package/src/harness_context/application/workspace_service.py +18 -0
- package/src/harness_context/bootstrap.py +47 -0
- package/src/harness_context/branding.py +16 -0
- package/src/harness_context/cli/__init__.py +1 -0
- package/src/harness_context/cli/app.py +239 -0
- package/src/harness_context/cli/exit_codes.py +25 -0
- package/src/harness_context/domain/__init__.py +9 -0
- package/src/harness_context/domain/cag.py +18 -0
- package/src/harness_context/domain/chunking.py +17 -0
- package/src/harness_context/domain/planning.py +30 -0
- package/src/harness_context/domain/ports.py +24 -0
- package/src/harness_context/domain/retrieval.py +46 -0
- package/src/harness_context/engine.py +10 -0
- package/src/harness_context/free_tools.py +143 -0
- package/src/harness_context/infrastructure/__init__.py +10 -0
- package/src/harness_context/infrastructure/graph.py +26 -0
- package/src/harness_context/infrastructure/indexes.py +33 -0
- package/src/harness_context/infrastructure/local_engine.py +296 -0
- package/src/harness_context/infrastructure/parsing.py +38 -0
- package/src/harness_context/infrastructure/scanning.py +51 -0
- package/src/harness_context/installer/__init__.py +4 -0
- package/src/harness_context/installer/models.py +22 -0
- package/src/harness_context/installer/service.py +168 -0
- package/src/harness_context/mcp/__init__.py +3 -0
- package/src/harness_context/mcp/capabilities.py +11 -0
- package/src/harness_context/mcp/errors.py +8 -0
- package/src/harness_context/mcp/lifecycle.py +72 -0
- package/src/harness_context/mcp/middleware.py +57 -0
- package/src/harness_context/mcp/server.py +3 -0
- package/src/harness_context/mcp/tool_handlers/__init__.py +7 -0
- package/src/harness_context/mcp/tool_handlers/context.py +16 -0
- package/src/harness_context/mcp/tool_handlers/ecc.py +8 -0
- package/src/harness_context/mcp/tool_handlers/handoffs.py +20 -0
- package/src/harness_context/mcp/tool_handlers/memory.py +16 -0
- package/src/harness_context/mcp/tool_handlers/workspace.py +12 -0
- package/src/harness_context/mcp/tools.py +15 -0
- package/src/harness_context/observability/__init__.py +6 -0
- package/src/harness_context/observability/events.py +25 -0
- package/src/harness_context/observability/metrics.py +20 -0
- package/src/harness_context/paths.py +35 -0
- package/src/harness_context/runtime.py +127 -0
- package/src/harness_context/schemas.py +38 -0
- package/src/harness_context/security/__init__.py +3 -0
- package/src/harness_context/security/secret_patterns.py +15 -0
- package/src/harness_context/server.py +1077 -0
- package/src/harness_context/storage/__init__.py +6 -0
- package/src/harness_context/storage/migrations.py +24 -0
- package/src/harness_context/storage/pins.py +10 -0
- package/src/harness_context/storage/snapshots.py +149 -0
- package/src/harness_context/tokenize.py +12 -0
- package/src/harness_context/topology.py +65 -0
- package/src/harness_context/watcher/__init__.py +3 -0
- package/src/harness_context/watcher/service.py +32 -0
- package/src/harness_context/workspace/__init__.py +13 -0
- package/src/harness_context/workspace/identity.py +9 -0
- package/src/harness_context/workspace/lock.py +24 -0
- package/src/harness_context/workspace/policy.py +3 -0
- package/src/harness_context/workspace/roots.py +84 -0
- package/src/harness_context/workspace/state.py +35 -0
- package/src/memory/episodic.py +257 -0
- package/src/memory/vector_store.py +104 -0
- package/src/retrieval/bm25.py +23 -0
- package/src/retrieval/cache.py +76 -0
- package/src/retrieval/embeddings.py +75 -0
- package/src/retrieval/graph.py +45 -0
- package/src/retrieval/reranker.py +78 -0
- package/src/retrieval/tokenize.py +11 -0
package/README.vi.md
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# CTXORA Engine
|
|
4
|
+
|
|
5
|
+
### Index once. Ground every agent.
|
|
6
|
+
|
|
7
|
+
**Context engine local-first dành cho coding agent.**
|
|
8
|
+
|
|
9
|
+
[](https://github.com/nguyentrunghieutcu/ctxora-engine/actions/workflows/ci.yml)
|
|
10
|
+
[](https://www.npmjs.com/package/ctxora)
|
|
11
|
+
[](https://skills.sh/nguyentrunghieutcu/ctxora-engine)
|
|
12
|
+
[](https://www.python.org/)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
[](#quyền-riêng-tư-và-bảo-mật)
|
|
15
|
+
[](docs/PRICING.md)
|
|
16
|
+
|
|
17
|
+
[English](README.md) · **Tiếng Việt**
|
|
18
|
+
|
|
19
|
+
[Bắt đầu nhanh](#bắt-đầu-nhanh) · [Cài đặt](#cài-đặt) · [Agent skills](#agent-skills) · [CLI](#tham-chiếu-cli) · [MCP](#mcp-tools) · [Bảo mật](#quyền-riêng-tư-và-bảo-mật)
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
> [!IMPORTANT]
|
|
24
|
+
> **Nguồn chính thức:** dùng package `ctxora` trên npm hoặc GitHub repository này. Gói `ctxora-engine` không được phát hành trên PyPI. Các package bên thứ ba sử dụng tên CTXORA không được dự án duy trì hoặc kiểm duyệt.
|
|
25
|
+
|
|
26
|
+
CTXORA Engine xây dựng biểu diễn local có thể tái sử dụng của repository và cung cấp đúng evidence cho Codex, Claude Code, Cursor, GitHub Copilot hoặc bất kỳ agent hỗ trợ MCP nào. Source code, index, embedding, graph, memory và handoff đều nằm trên máy của bạn.
|
|
27
|
+
|
|
28
|
+
## Bắt đầu nhanh
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx ctxora setup --workspace /duong-dan/toi/project
|
|
32
|
+
npx ctxora index --workspace /duong-dan/toi/project
|
|
33
|
+
npx ctxora explain --workspace /duong-dan/toi/project \
|
|
34
|
+
"Authentication được triển khai ở đâu?"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Kết quả là JSON có cấu trúc, gồm file liên quan, symbol, tín hiệu dependency, provenance, coverage diagnostics và test hoặc convention được đề xuất khi có thể xác định.
|
|
38
|
+
|
|
39
|
+
## Vì sao cần CTXORA?
|
|
40
|
+
|
|
41
|
+
Coding agent thường tốn token để khám phá lại repository, chọn sai layer, bỏ sót convention hoặc mất context giữa các phiên. Instruction file tĩnh giúp định hướng, nhưng không tự chọn evidence phù hợp với từng task.
|
|
42
|
+
|
|
43
|
+
CTXORA bổ sung một lớp context local:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
Repository
|
|
47
|
+
↓ scan, parse, chunk
|
|
48
|
+
Immutable local snapshot
|
|
49
|
+
↓ lexical + semantic + symbol + path + graph indexes
|
|
50
|
+
Context planner
|
|
51
|
+
↓ CAG / RAG / long context / graph-augmented retrieval
|
|
52
|
+
Codex · Claude Code · Cursor · Copilot · MCP clients
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- **Giảm sửa sai file** — tìm module, dependency path và test liên quan.
|
|
56
|
+
- **Giảm prompt lặp lại** — tái sử dụng kiến thức repository giữa nhiều phiên agent.
|
|
57
|
+
- **Không khóa vào một agent** — một engine phục vụ nhiều coding tool.
|
|
58
|
+
- **Riêng tư mặc định** — không hosted index, remote telemetry hoặc cloud account bắt buộc.
|
|
59
|
+
- **Evidence có thể kiểm tra** — mỗi kết quả đều có source path và provenance.
|
|
60
|
+
|
|
61
|
+
## Bạn nhận được gì
|
|
62
|
+
|
|
63
|
+
### Local context engine
|
|
64
|
+
|
|
65
|
+
- AST-aware chunking cho Python, JavaScript và TypeScript; fallback chunking có giới hạn cho định dạng text khác.
|
|
66
|
+
- Hybrid lexical và local semantic retrieval bằng BM25, TF-IDF/LSA, keyword overlap, symbol và path.
|
|
67
|
+
- Code dependency graph và graph-augmented context selection.
|
|
68
|
+
- Các strategy CAG, RAG, hybrid CAG/RAG, long context và graph augmented.
|
|
69
|
+
- Immutable snapshot với candidate validation, atomic promotion, recovery và incremental refresh.
|
|
70
|
+
- SQLite memory và raw conversation handoff theo workspace.
|
|
71
|
+
- Token budgeting cho context window của OpenAI, Anthropic và Gemini.
|
|
72
|
+
|
|
73
|
+
### Onboarding coding agent
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
ctxora repo-map --workspace .
|
|
77
|
+
ctxora context-score --workspace .
|
|
78
|
+
ctxora generate-agents-md --workspace .
|
|
79
|
+
ctxora generate-copilot-instructions --workspace .
|
|
80
|
+
ctxora generate-cursor-rules --workspace .
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Các instruction file được sinh theo cách deterministic và không ghi đè file hiện có nếu thiếu `--force`.
|
|
84
|
+
|
|
85
|
+
### An toàn và vận hành
|
|
86
|
+
|
|
87
|
+
- Authorization theo canonical workspace root và chặn symlink thoát khỏi root.
|
|
88
|
+
- Loại secret-like file, binary, dependency, VCS, generated state và file quá lớn.
|
|
89
|
+
- Nội dung repository được retrieve luôn là untrusted evidence, không phải agent instruction.
|
|
90
|
+
- Machine-readable diagnostics, context health report, evaluation gate và CLI exit code ổn định.
|
|
91
|
+
- `ctxora ci` local để index file thay đổi giữa hai Git ref.
|
|
92
|
+
|
|
93
|
+
## Cài đặt
|
|
94
|
+
|
|
95
|
+
### npm / npx — khuyến nghị
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npx ctxora setup --workspace /duong-dan/toi/project
|
|
99
|
+
npx ctxora doctor --workspace /duong-dan/toi/project
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Npm launcher không có dependency ngoài, đóng gói source Python MIT và cài CTXORA Engine vào environment local theo version. Không cần cài Python package global hoặc tạo cloud account. Máy cần có sẵn Python 3.10–3.13.
|
|
103
|
+
|
|
104
|
+
Nếu muốn có shell command lâu dài:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm install --global ctxora
|
|
108
|
+
ctxora setup --workspace /duong-dan/toi/project
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Cài trực tiếp từ GitHub
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
python3 -m pip install \
|
|
115
|
+
"git+https://github.com/nguyentrunghieutcu/ctxora-engine.git"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Cài từ source clone
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git clone https://github.com/nguyentrunghieutcu/ctxora-engine.git
|
|
122
|
+
cd ctxora-engine
|
|
123
|
+
python3 -m pip install .
|
|
124
|
+
ctxora doctor --workspace .
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Môi trường phát triển
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
python3 -m venv .venv
|
|
131
|
+
source .venv/bin/activate
|
|
132
|
+
python -m pip install -e '.[dev]'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Yêu cầu: Python 3.10–3.13 và Git. Runtime state nằm trong `.ctxora/`; state `.harness/` cũ vẫn đọc được trong giai đoạn migration.
|
|
136
|
+
|
|
137
|
+
## Agent skills
|
|
138
|
+
|
|
139
|
+
Cài toàn bộ CTXORA skills từ repository này:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx skills add nguyentrunghieutcu/ctxora-engine
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Liệt kê hoặc chỉ cài một skill:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx skills add nguyentrunghieutcu/ctxora-engine --list
|
|
149
|
+
npx skills add nguyentrunghieutcu/ctxora-engine --skill ctxora-setup
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Pack gồm các workflow setup, grounded repository context và context health. Phiên bản hiện tại của `skills` CLI yêu cầu Node.js 22.20 trở lên.
|
|
153
|
+
|
|
154
|
+
## Kết nối coding agent
|
|
155
|
+
|
|
156
|
+
CTXORA có thể cập nhật an toàn cấu hình client được hỗ trợ và giữ nguyên các entry không liên quan:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
ctxora profile --workspace .
|
|
160
|
+
ctxora install --workspace . --profile codex
|
|
161
|
+
ctxora install --workspace . --profile claude-code
|
|
162
|
+
ctxora install --workspace . --profile cursor
|
|
163
|
+
ctxora install --workspace . --profile generic-mcp
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Dùng `--dry-run` để xem trước và `--client-config` để chọn file cấu hình khác mặc định.
|
|
167
|
+
|
|
168
|
+
| Profile | Cấu hình mặc định |
|
|
169
|
+
|---|---|
|
|
170
|
+
| Codex | `~/.codex/config.toml` |
|
|
171
|
+
| Claude Code | `~/.claude.json` |
|
|
172
|
+
| Cursor | `~/.cursor/mcp.json` |
|
|
173
|
+
| Generic MCP | `~/.config/mcp/servers.json` |
|
|
174
|
+
|
|
175
|
+
Cấu hình MCP thủ công:
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"mcpServers": {
|
|
180
|
+
"ctxora": {
|
|
181
|
+
"command": "ctxora",
|
|
182
|
+
"args": ["run", "--workspace", "/absolute/path/to/project", "--transport", "stdio"],
|
|
183
|
+
"env": {
|
|
184
|
+
"CTXORA_ALLOWED_ROOTS": "/absolute/path/to/project",
|
|
185
|
+
"PYTHONUTF8": "1"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Không commit cấu hình client chứa đường dẫn cá nhân.
|
|
193
|
+
|
|
194
|
+
## Workflow chính
|
|
195
|
+
|
|
196
|
+
### Tìm hiểu repository
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
ctxora setup --workspace .
|
|
200
|
+
ctxora index --workspace .
|
|
201
|
+
ctxora query --workspace . "Luồng xác thực request hoạt động thế nào?"
|
|
202
|
+
ctxora explain --workspace . "Nên sửa token rotation ở đâu?"
|
|
203
|
+
ctxora inspect --workspace . snapshot
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Refresh file thay đổi
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
ctxora index --workspace . --incremental
|
|
210
|
+
ctxora ci --workspace . --base origin/main --head HEAD
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Chạy MCP server
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# Transport local được khuyến nghị
|
|
217
|
+
ctxora run --workspace . --transport stdio
|
|
218
|
+
|
|
219
|
+
# HTTP local
|
|
220
|
+
ctxora run --workspace . --transport streamable-http \
|
|
221
|
+
--host 127.0.0.1 --port 8765
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Bind HTTP ra ngoài loopback cần `--allow-external` và phải được bảo vệ bằng authorization layer trước khi dùng production.
|
|
225
|
+
|
|
226
|
+
### Export và sửa local state
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
ctxora export --workspace . --output ./ctxora-snapshot.json
|
|
230
|
+
ctxora doctor --workspace .
|
|
231
|
+
ctxora repair --workspace .
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Tham chiếu CLI
|
|
235
|
+
|
|
236
|
+
| Command | Mục đích |
|
|
237
|
+
|---|---|
|
|
238
|
+
| `setup` | Tạo cấu hình local cho workspace. |
|
|
239
|
+
| `register` | Đăng ký và authorize workspace. |
|
|
240
|
+
| `run` | Chạy CTXORA MCP foreground. |
|
|
241
|
+
| `start`, `status`, `stop` | Quản lý background process local. |
|
|
242
|
+
| `index` | Build hoặc refresh local snapshot. |
|
|
243
|
+
| `query` | Trả về context package có cấu trúc. |
|
|
244
|
+
| `explain` | Giải thích vị trí và cách thực hiện thay đổi. |
|
|
245
|
+
| `context-score` | Chấm điểm độ sẵn sàng của repository context. |
|
|
246
|
+
| `repo-map` | Tạo repository map cô đọng. |
|
|
247
|
+
| `inspect` | Xem workspace, snapshot, bundle hoặc ECC state. |
|
|
248
|
+
| `doctor`, `repair` | Chẩn đoán hoặc build lại local state. |
|
|
249
|
+
| `export` | Export snapshot ra JSON. |
|
|
250
|
+
| `profile` | Liệt kê coding-agent profile được hỗ trợ. |
|
|
251
|
+
| `install`, `uninstall` | Thêm hoặc gỡ cấu hình MCP client an toàn. |
|
|
252
|
+
| `ci` | Refresh file thay đổi giữa hai Git ref. |
|
|
253
|
+
| `generate-agents-md` | Sinh repository instructions cho agent. |
|
|
254
|
+
| `generate-copilot-instructions` | Sinh GitHub Copilot instructions. |
|
|
255
|
+
| `generate-cursor-rules` | Sinh Cursor rules. |
|
|
256
|
+
| `pro` | Hiển thị trạng thái waitlist, không cài paid feature. |
|
|
257
|
+
|
|
258
|
+
Mọi command đều hỗ trợ `--workspace`. Chạy `ctxora <command> --help` để xem option cụ thể.
|
|
259
|
+
|
|
260
|
+
## MCP tools
|
|
261
|
+
|
|
262
|
+
CTXORA MCP hiện cung cấp 24 tools.
|
|
263
|
+
|
|
264
|
+
### Context và workspace
|
|
265
|
+
|
|
266
|
+
| Tool | Mục đích |
|
|
267
|
+
|---|---|
|
|
268
|
+
| `register_workspace` | Đăng ký repository root được phép. |
|
|
269
|
+
| `refresh_workspace` | Build hoặc incremental refresh snapshot. |
|
|
270
|
+
| `plan_context` | Chọn retrieval strategy cho task. |
|
|
271
|
+
| `retrieve_context` | Trả ranked evidence và coverage diagnostics. |
|
|
272
|
+
| `prepare_context` | Tạo context package theo token budget. |
|
|
273
|
+
| `context_stats` | Xem thống kê index và snapshot. |
|
|
274
|
+
| `invalidate_context` | Invalidate index hoặc cached state. |
|
|
275
|
+
| `retrieve_context_legacy` | Compatibility entry point cho client cũ. |
|
|
276
|
+
|
|
277
|
+
### Memory và handoff
|
|
278
|
+
|
|
279
|
+
| Tool | Mục đích |
|
|
280
|
+
|---|---|
|
|
281
|
+
| `memory_save`, `memory_search`, `memory_inject` | Lưu, tìm và inject knowledge theo scope. |
|
|
282
|
+
| `memory_list`, `memory_delete`, `memory_evict`, `memory_stats` | Quản lý vòng đời local memory. |
|
|
283
|
+
| `handoff_conversation` | Lưu raw provider-format conversation handoff. |
|
|
284
|
+
| `restore_conversation_handoff` | Khôi phục handoff được chọn rõ ràng. |
|
|
285
|
+
| `list_conversation_handoffs` | Liệt kê handoff còn lưu. |
|
|
286
|
+
| `delete_conversation_handoff`, `purge_expired_handoffs` | Xóa handoff được chọn hoặc đã hết hạn. |
|
|
287
|
+
|
|
288
|
+
### Tiện ích
|
|
289
|
+
|
|
290
|
+
| Tool | Mục đích |
|
|
291
|
+
|---|---|
|
|
292
|
+
| `estimate_tokens` | Ước tính token cho text. |
|
|
293
|
+
| `get_token_budget` | Trả context budget và reserved headroom của model. |
|
|
294
|
+
| `invalidate_cache` | Xóa retrieval cache. |
|
|
295
|
+
| `reindex_paths` | Force reindex các path được chọn. |
|
|
296
|
+
|
|
297
|
+
JSON Schema API v2 nằm tại [`schemas/mcp-v2/`](schemas/mcp-v2/).
|
|
298
|
+
|
|
299
|
+
## Retrieval strategies
|
|
300
|
+
|
|
301
|
+
| Strategy | Phù hợp với |
|
|
302
|
+
|---|---|
|
|
303
|
+
| `cag` | Instruction ổn định và repository knowledge cô đọng. |
|
|
304
|
+
| `hybrid_rag` | Câu hỏi code cần ranked evidence tập trung. |
|
|
305
|
+
| `long_context` | Repository nhỏ nằm trong token budget. |
|
|
306
|
+
| `hybrid_cag_rag` | Guidance ổn định kết hợp evidence theo task. |
|
|
307
|
+
| `graph_augmented` | Kiến trúc, call path, dependency và impact analysis. |
|
|
308
|
+
|
|
309
|
+
Planner deterministic và có thể override khi caller cần strategy cụ thể.
|
|
310
|
+
|
|
311
|
+
## Tích hợp ECC
|
|
312
|
+
|
|
313
|
+
CTXORA có thể đọc vault format [`ecc.memory.v1`](https://github.com/affaan-m/ECC) như external context tùy chọn. CTXORA không cài, clone, gọi hoặc sửa ECC.
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
ctxora run --workspace . --transport stdio --ecc
|
|
317
|
+
ctxora inspect --workspace . --ecc ecc
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Project memory tại `.ecc/memory` chỉ được đọc. User memory tại `~/.ecc/memory` bị tắt trừ khi bật `--ecc-user-scope` hoặc `ecc_allow_user_scope = true`. Memory import có external provenance và trạng thái unreviewed trust.
|
|
321
|
+
|
|
322
|
+
## Kiến trúc
|
|
323
|
+
|
|
324
|
+
```text
|
|
325
|
+
CLI / MCP / CI transports
|
|
326
|
+
↓
|
|
327
|
+
Application services
|
|
328
|
+
↓
|
|
329
|
+
Domain contracts and planning
|
|
330
|
+
↓
|
|
331
|
+
Local scanners · parsers · indexes · graph · snapshots · SQLite
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Production package dùng `src/` layout. `harness_context` vẫn là internal Python namespace để tương thích; branding và command public dùng CTXORA. Xem [Architecture](docs/ARCHITECTURE.md) và [OSS release scope](docs/OSS-IMPLEMENTATION-PLAN.md).
|
|
335
|
+
|
|
336
|
+
## Quyền riêng tư và bảo mật
|
|
337
|
+
|
|
338
|
+
- Không remote telemetry mặc định.
|
|
339
|
+
- Không yêu cầu cloud account hoặc hosted index.
|
|
340
|
+
- Workspace root được authorize và canonicalize rõ ràng.
|
|
341
|
+
- Symlink không thể thoát khỏi root được phép.
|
|
342
|
+
- Secret-like và binary file bị loại trước indexing.
|
|
343
|
+
- Retrieved source là untrusted evidence và không thể ghi đè agent instruction.
|
|
344
|
+
- External HTTP là opt-in và cần authorization layer do bạn quản lý.
|
|
345
|
+
|
|
346
|
+
Báo cáo lỗ hổng qua [GitHub Private Vulnerability Reporting](https://github.com/nguyentrunghieutcu/ctxora-engine/security/advisories/new). Nếu kênh đó không dùng được, gửi email tới `nguyentrunghieutcu@gmail.com`. Xem [SECURITY.md](SECURITY.md).
|
|
347
|
+
|
|
348
|
+
## Free và Pro
|
|
349
|
+
|
|
350
|
+
### CTXORA Free — đã có
|
|
351
|
+
|
|
352
|
+
Toàn bộ local engine trong repository MIT này miễn phí và không giới hạn: manual indexing, CAG/RAG/graph retrieval, MCP, local memory, handoff, health tools, repository map và instruction generation.
|
|
353
|
+
|
|
354
|
+
### CTXORA Pro — waitlist
|
|
355
|
+
|
|
356
|
+
Phạm vi trả phí dự kiến chỉ gồm managed repository automation, private workflow operations và shared team context. Billing, entitlement, hosted automation và team service chưa được triển khai trong repository này. `ctxora pro` chỉ trả thông tin waitlist.
|
|
357
|
+
|
|
358
|
+
Xem [product boundary](docs/PRICING.md).
|
|
359
|
+
|
|
360
|
+
## Cấu trúc project
|
|
361
|
+
|
|
362
|
+
```text
|
|
363
|
+
src/harness_context/ Runtime, domain, application, MCP, CLI, storage
|
|
364
|
+
src/chunking/ AST-aware và fallback chunking
|
|
365
|
+
src/context/ Assembly, sanitization, token budgeting
|
|
366
|
+
src/retrieval/ BM25, local embeddings, graph, reranking, cache
|
|
367
|
+
src/memory/ Local episodic và vector memory
|
|
368
|
+
src/compact/ Provider handoff và compaction helpers
|
|
369
|
+
src/evaluation/ Quality metrics và release gates
|
|
370
|
+
bin/ npm/npx launcher không có dependency ngoài
|
|
371
|
+
skills/ Coding-agent skills có thể cài đặt
|
|
372
|
+
schemas/mcp-v2/ API v2 JSON Schemas công khai
|
|
373
|
+
tests/ Unit, security, evaluation, E2E, packaging tests
|
|
374
|
+
scripts/ Install, uninstall, migration, topology audit
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Phát triển và kiểm tra
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
npm test
|
|
381
|
+
npm pack --dry-run
|
|
382
|
+
ruff check .
|
|
383
|
+
python scripts/audit_topology.py
|
|
384
|
+
python -m unittest discover -s tests -t . -v
|
|
385
|
+
python -m evaluation.gates
|
|
386
|
+
python -m compileall -q src tests scripts
|
|
387
|
+
git diff --check
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
CI matrix chạy Python 3.10, 3.11, 3.12 và 3.13. Evaluation fixture bao gồm Python, TypeScript, Flutter, monorepo, tiếng Việt, malicious prompt-like file, long document và duplicate symbol.
|
|
391
|
+
|
|
392
|
+
## Xử lý sự cố
|
|
393
|
+
|
|
394
|
+
### Không tìm thấy `ctxora`
|
|
395
|
+
|
|
396
|
+
Dùng npm launcher mà không cần cài global command:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
npx ctxora --version
|
|
400
|
+
npx ctxora doctor --workspace .
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Workspace bị từ chối
|
|
404
|
+
|
|
405
|
+
Dùng đường dẫn tuyệt đối đang tồn tại và bảo đảm nó nằm trong `CTXORA_ALLOWED_ROOTS` nếu MCP client thiết lập allowlist.
|
|
406
|
+
|
|
407
|
+
### Instruction file hiện có không được thay thế
|
|
408
|
+
|
|
409
|
+
Đây là hành vi chủ động để bảo vệ dữ liệu. Kiểm tra output hoặc chỉ chạy lại với `--force` khi thật sự muốn ghi đè.
|
|
410
|
+
|
|
411
|
+
### HTTP binding bị từ chối
|
|
412
|
+
|
|
413
|
+
Loopback là security boundary mặc định. Chỉ dùng `--allow-external` phía sau authentication và network-access layer do bạn kiểm soát.
|
|
414
|
+
|
|
415
|
+
### Cần build lại local state
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
ctxora doctor --workspace .
|
|
419
|
+
ctxora repair --workspace .
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
## Tài liệu
|
|
423
|
+
|
|
424
|
+
- [OSS release scope](docs/OSS-IMPLEMENTATION-PLAN.md)
|
|
425
|
+
- [Architecture](docs/ARCHITECTURE.md)
|
|
426
|
+
- [Operations](docs/OPERATIONS.md)
|
|
427
|
+
- [Free và Pro boundary](docs/PRICING.md)
|
|
428
|
+
- [Security policy](SECURITY.md)
|
|
429
|
+
- [Support policy](SUPPORT.md)
|
|
430
|
+
- [Contributing](CONTRIBUTING.md)
|
|
431
|
+
- [Changelog](CHANGELOG.md)
|
|
432
|
+
|
|
433
|
+
## Cộng đồng
|
|
434
|
+
|
|
435
|
+
- Mở [GitHub issue](https://github.com/nguyentrunghieutcu/ctxora-engine/issues) cho bug tái hiện được và feature request.
|
|
436
|
+
- Dùng private vulnerability reporting cho vấn đề bảo mật.
|
|
437
|
+
- Chào đón contribution giữ nguyên local-first và paid-control-plane independence boundary.
|
|
438
|
+
|
|
439
|
+
## License
|
|
440
|
+
|
|
441
|
+
CTXORA Engine được phát hành theo [MIT License](LICENSE).
|
package/bin/ctxora.mjs
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
|
|
9
|
+
const PACKAGE_VERSION = "6.2.0";
|
|
10
|
+
const PYTHON_RANGE = "3.10-3.13";
|
|
11
|
+
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
12
|
+
|
|
13
|
+
function fail(message) {
|
|
14
|
+
console.error(`ctxora: ${message}`);
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function run(command, args, options = {}) {
|
|
19
|
+
return spawnSync(command, args, {
|
|
20
|
+
encoding: "utf8",
|
|
21
|
+
stdio: options.capture ? "pipe" : "inherit",
|
|
22
|
+
env: options.env ?? process.env,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function parsePythonVersion(output) {
|
|
27
|
+
const match = output.match(/Python\s+(\d+)\.(\d+)\.(\d+)/);
|
|
28
|
+
return match ? match.slice(1).map(Number) : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isSupportedPython(version) {
|
|
32
|
+
return Boolean(version && version[0] === 3 && version[1] >= 10 && version[1] <= 13);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function pythonCandidates() {
|
|
36
|
+
if (process.env.CTXORA_PYTHON) {
|
|
37
|
+
return [{ command: process.env.CTXORA_PYTHON, prefix: [] }];
|
|
38
|
+
}
|
|
39
|
+
return process.platform === "win32"
|
|
40
|
+
? [{ command: "py", prefix: ["-3"] }, { command: "python", prefix: [] }, { command: "python3", prefix: [] }]
|
|
41
|
+
: [{ command: "python3", prefix: [] }, { command: "python", prefix: [] }];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function findPython() {
|
|
45
|
+
for (const candidate of pythonCandidates()) {
|
|
46
|
+
const result = run(candidate.command, [...candidate.prefix, "--version"], { capture: true });
|
|
47
|
+
const version = parsePythonVersion(`${result.stdout ?? ""}${result.stderr ?? ""}`);
|
|
48
|
+
if (!result.error && result.status === 0 && isSupportedPython(version)) {
|
|
49
|
+
return candidate;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function runtimeRoot(environment = process.env) {
|
|
56
|
+
if (environment.CTXORA_HOME) return resolve(environment.CTXORA_HOME);
|
|
57
|
+
if (process.platform === "win32") {
|
|
58
|
+
return join(environment.LOCALAPPDATA || join(homedir(), "AppData", "Local"), "CTXORA");
|
|
59
|
+
}
|
|
60
|
+
return join(environment.XDG_DATA_HOME || join(homedir(), ".local", "share"), "ctxora");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function runtimePython(runtimeDirectory) {
|
|
64
|
+
return process.platform === "win32"
|
|
65
|
+
? join(runtimeDirectory, "venv", "Scripts", "python.exe")
|
|
66
|
+
: join(runtimeDirectory, "venv", "bin", "python");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function markerMatches(markerPath) {
|
|
70
|
+
try {
|
|
71
|
+
const marker = JSON.parse(readFileSync(markerPath, "utf8"));
|
|
72
|
+
return marker.packageVersion === PACKAGE_VERSION;
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function installRuntime(systemPython, runtimeDirectory) {
|
|
79
|
+
const parent = dirname(runtimeDirectory);
|
|
80
|
+
mkdirSync(parent, { recursive: true });
|
|
81
|
+
const staging = join(parent, `.install-${process.pid}-${Date.now()}`);
|
|
82
|
+
rmSync(staging, { recursive: true, force: true });
|
|
83
|
+
|
|
84
|
+
const create = run(systemPython.command, [...systemPython.prefix, "-m", "venv", join(staging, "venv")]);
|
|
85
|
+
if (create.error || create.status !== 0) {
|
|
86
|
+
rmSync(staging, { recursive: true, force: true });
|
|
87
|
+
throw new Error("could not create the managed Python environment");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const python = runtimePython(staging);
|
|
91
|
+
const install = run(python, [
|
|
92
|
+
"-m", "pip", "install", "--disable-pip-version-check", "--upgrade", PACKAGE_ROOT,
|
|
93
|
+
]);
|
|
94
|
+
if (install.error || install.status !== 0) {
|
|
95
|
+
rmSync(staging, { recursive: true, force: true });
|
|
96
|
+
throw new Error("could not install CTXORA Engine into the managed environment");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
writeFileSync(join(staging, "install.json"), `${JSON.stringify({ packageVersion: PACKAGE_VERSION }, null, 2)}\n`);
|
|
100
|
+
rmSync(runtimeDirectory, { recursive: true, force: true });
|
|
101
|
+
renameSync(staging, runtimeDirectory);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function ensureRuntime() {
|
|
105
|
+
const runtimeDirectory = join(runtimeRoot(), "runtime", PACKAGE_VERSION);
|
|
106
|
+
const python = runtimePython(runtimeDirectory);
|
|
107
|
+
if (existsSync(python) && markerMatches(join(runtimeDirectory, "install.json"))) return python;
|
|
108
|
+
|
|
109
|
+
const systemPython = findPython();
|
|
110
|
+
if (!systemPython) throw new Error(`Python ${PYTHON_RANGE} is required`);
|
|
111
|
+
installRuntime(systemPython, runtimeDirectory);
|
|
112
|
+
return runtimePython(runtimeDirectory);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function printHelp() {
|
|
116
|
+
console.log(`CTXORA Engine ${PACKAGE_VERSION}\n\nUsage:\n npx ctxora setup --workspace <path>\n npx ctxora <command> [options]\n\nThe npm launcher installs CTXORA Engine into a versioned local Python environment.\nRun \"npx ctxora setup --help\" for engine command help.`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function main(args = process.argv.slice(2)) {
|
|
120
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
121
|
+
printHelp();
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
if (args[0] === "--version" || args[0] === "-V") {
|
|
125
|
+
console.log(PACKAGE_VERSION);
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const python = ensureRuntime();
|
|
131
|
+
const environment = {
|
|
132
|
+
...process.env,
|
|
133
|
+
CTXORA_MCP_COMMAND: python,
|
|
134
|
+
CTXORA_MCP_ARGS_PREFIX: JSON.stringify(["-m", "harness_context.cli.app"]),
|
|
135
|
+
};
|
|
136
|
+
const result = run(python, ["-m", "harness_context.cli.app", ...args], { env: environment });
|
|
137
|
+
if (result.error) throw result.error;
|
|
138
|
+
return result.status ?? 1;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
141
|
+
return 1;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
146
|
+
process.exitCode = main();
|
|
147
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ctxora",
|
|
3
|
+
"version": "6.2.0",
|
|
4
|
+
"description": "Local-first context engine for coding agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ctxora": "bin/ctxora.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"src/**/*.py",
|
|
12
|
+
"pyproject.toml",
|
|
13
|
+
"README.md",
|
|
14
|
+
"README.vi.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "node --test tests/npm/*.test.mjs"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"ai-agents",
|
|
25
|
+
"coding-agents",
|
|
26
|
+
"context-engineering",
|
|
27
|
+
"mcp",
|
|
28
|
+
"rag",
|
|
29
|
+
"codex",
|
|
30
|
+
"claude-code",
|
|
31
|
+
"cursor"
|
|
32
|
+
],
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/nguyentrunghieutcu/ctxora-engine.git"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/nguyentrunghieutcu/ctxora-engine#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/nguyentrunghieutcu/ctxora-engine/issues"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/pyproject.toml
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=75", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ctxora-engine"
|
|
7
|
+
version = "6.2.0"
|
|
8
|
+
description = "Local-first context engine for coding agents."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"mcp>=1.0,<2",
|
|
13
|
+
"networkx>=3.2,<4",
|
|
14
|
+
"numpy>=1.26,<3",
|
|
15
|
+
"rank-bm25>=0.2.2,<0.3",
|
|
16
|
+
"scikit-learn>=1.4,<2",
|
|
17
|
+
"tiktoken>=0.7,<1",
|
|
18
|
+
"tomli>=2,<3; python_version < '3.11'",
|
|
19
|
+
"tree-sitter>=0.22,<0.26",
|
|
20
|
+
"tree-sitter-javascript>=0.23,<0.24",
|
|
21
|
+
"tree-sitter-python>=0.23,<0.24",
|
|
22
|
+
"tree-sitter-typescript>=0.23,<0.24",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
dev = ["pytest>=8,<9", "ruff>=0.12,<1", "mypy>=1.17,<2"]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
ctxora-mcp = "harness_context.server:main"
|
|
30
|
+
ctxora = "harness_context.cli.app:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
package-dir = {"" = "src"}
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
37
|
+
include = ["harness_context*", "chunking*", "compact*", "context*", "memory*", "retrieval*", "evaluation*"]
|
|
38
|
+
|
|
39
|
+
[tool.pytest.ini_options]
|
|
40
|
+
testpaths = ["tests"]
|
|
41
|
+
|
|
42
|
+
[tool.mypy]
|
|
43
|
+
python_version = "3.10"
|
|
44
|
+
check_untyped_defs = true
|
|
45
|
+
ignore_missing_imports = true
|
|
46
|
+
|
|
47
|
+
[tool.ruff]
|
|
48
|
+
target-version = "py310"
|
|
49
|
+
line-length = 100
|
|
50
|
+
|
|
51
|
+
[tool.ruff.lint.per-file-ignores]
|
|
52
|
+
"src/chunking/treesitter_chunker.py" = ["BLE001"]
|
|
53
|
+
"src/compact/gemini.py" = ["SIM102"]
|
|
54
|
+
"src/compact/openai.py" = ["BLE001"]
|
|
55
|
+
"src/harness_context/domain/planning.py" = ["RUF012"]
|
|
56
|
+
"src/harness_context/server.py" = ["BLE001", "G201"]
|
|
57
|
+
"src/harness_context/watcher/service.py" = ["BLE001", "S112"]
|
|
58
|
+
"tests/packaging/test_clean_environment.py" = ["ISC004", "PLW1510"]
|
|
59
|
+
"tests/test_phase_b_workspace_storage.py" = ["BLE001", "SIM117"]
|