kc-beta 0.2.1 → 0.3.1
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/QUICKSTART.md +149 -0
- package/README.md +207 -0
- package/package.json +12 -2
- package/src/agent/context.js +8 -4
- package/src/agent/engine.js +154 -9
- package/src/agent/pipelines/initializer.js +53 -8
- package/src/agent/session-state.js +1 -0
- package/src/agent/skill-loader.js +13 -1
- package/src/agent/task-manager.js +186 -0
- package/src/agent/tools/document-parse.js +99 -21
- package/src/agent/tools/document-search.js +24 -8
- package/src/agent/tools/sandbox-exec.js +16 -5
- package/src/agent/tools/workspace-file.js +47 -20
- package/src/agent/workspace.js +24 -1
- package/src/cli/components.js +42 -1
- package/src/cli/config.js +100 -6
- package/src/cli/index.js +39 -2
- package/src/cli/onboard.js +70 -1
- package/src/config.js +43 -3
- package/src/model-tiers.json +153 -0
- package/src/providers.js +63 -66
- package/template/AGENT.md +20 -0
- package/template/skills/en/meta/compliance-judgment/SKILL.md +10 -42
- package/template/skills/en/meta/document-chunking/SKILL.md +32 -0
- package/template/skills/en/meta/document-parsing/SKILL.md +11 -18
- package/template/skills/en/meta/entity-extraction/SKILL.md +13 -28
- package/template/skills/en/meta/tree-processing/SKILL.md +19 -1
- package/template/skills/en/meta-meta/auto-model-selection/SKILL.md +53 -0
- package/template/skills/en/meta-meta/pdf-review-dashboard/SKILL.md +57 -0
- package/template/skills/en/meta-meta/pdf-review-dashboard/scripts/generate_review.js +262 -0
- package/template/skills/en/meta-meta/rule-extraction/SKILL.md +24 -1
- package/template/skills/en/meta-meta/skill-authoring/SKILL.md +6 -0
- package/template/skills/en/meta-meta/skill-to-workflow/SKILL.md +4 -0
- package/template/skills/zh/meta/compliance-judgment/SKILL.md +41 -262
- package/template/skills/zh/meta/document-chunking/SKILL.md +32 -0
- package/template/skills/zh/meta/document-parsing/SKILL.md +65 -132
- package/template/skills/zh/meta/entity-extraction/SKILL.md +68 -230
- package/template/skills/zh/meta/tree-processing/SKILL.md +82 -194
- package/template/skills/zh/meta-meta/auto-model-selection/SKILL.md +51 -0
- package/template/skills/zh/meta-meta/pdf-review-dashboard/SKILL.md +55 -0
- package/template/skills/zh/meta-meta/pdf-review-dashboard/scripts/generate_review.js +262 -0
- package/template/skills/zh/meta-meta/rule-extraction/SKILL.md +79 -164
- package/template/skills/zh/meta-meta/skill-authoring/SKILL.md +64 -185
- package/template/skills/zh/meta-meta/skill-to-workflow/SKILL.md +95 -216
package/QUICKSTART.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# KC Agent CLI (Beta) — Quickstart
|
|
2
|
+
|
|
3
|
+
## Install
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g kc-beta
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Requires **Node.js 20+**.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Run the onboarding wizard to configure your LLM provider and API keys:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
kc-beta onboard
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
You'll be prompted to choose:
|
|
20
|
+
|
|
21
|
+
1. **Language** — English or 中文
|
|
22
|
+
2. **LLM Provider** — SiliconFlow, Aliyun Bailian, Anthropic, OpenAI, VolcanoCloud, Zhipu GLM, MiniMax, OpenRouter, or custom
|
|
23
|
+
3. **API Key** — your provider API key (supports both API keys and Aliyun/VolcanoCloud coding plan keys)
|
|
24
|
+
4. **Model Discovery** — KC auto-discovers available models via API or curated lists and suggests tier assignments with capability-based ranking
|
|
25
|
+
5. **Conductor Model** — the main model that drives the agent
|
|
26
|
+
6. **Worker LLM Tiers** — tier1 (best) through tier4 (cheapest) for verification tasks
|
|
27
|
+
7. **VLM Tiers** — vision models for OCR/document parsing (tier1-3)
|
|
28
|
+
8. **Worker Provider** (optional) — use a different provider for worker LLMs (defaults to conductor provider)
|
|
29
|
+
|
|
30
|
+
Config is saved to `~/.kc_agent/config.json` and shared across projects.
|
|
31
|
+
|
|
32
|
+
### Edit Settings Later
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
kc-beta config
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Category-based editor for: LLM provider, model tiers, VLM tiers, worker LLM provider, quality thresholds, language.
|
|
39
|
+
|
|
40
|
+
## Create a Project
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
kc-beta init my-project
|
|
44
|
+
kc-beta init my-project --lang=zh # Chinese skills
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This creates a workspace with:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
my-project/
|
|
51
|
+
.env # Project-level config (overrides global)
|
|
52
|
+
Rules/ # Put regulation documents here
|
|
53
|
+
Samples/ # Put sample documents here
|
|
54
|
+
Input/ # Production batches
|
|
55
|
+
Output/ # Verification results
|
|
56
|
+
skills/ # Meta-methodology skills (en or zh)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Start the Agent
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
kc-beta # default language from config
|
|
63
|
+
kc-beta --en # this session in English (does not change config)
|
|
64
|
+
kc-beta --zh # this session in Chinese (does not change config)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Launch from your project directory — KC has full read/write access to the folder you launch from:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
cd my-project
|
|
71
|
+
kc-beta
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The agent starts in **BOOTSTRAP** phase. It will:
|
|
75
|
+
|
|
76
|
+
1. Set up the workspace structure
|
|
77
|
+
2. Detect regulations and samples in your project directory
|
|
78
|
+
3. Ask about your verification scenario
|
|
79
|
+
|
|
80
|
+
Once regulations and samples are in place, the agent advances through 6 phases automatically:
|
|
81
|
+
|
|
82
|
+
| Phase | What happens |
|
|
83
|
+
|-------|-------------|
|
|
84
|
+
| **BOOTSTRAP** | Workspace setup, understand the scenario |
|
|
85
|
+
| **EXTRACTION** | Decompose regulations into atomic rules |
|
|
86
|
+
| **SKILL_AUTHORING** | Write verification skills for each rule |
|
|
87
|
+
| **SKILL_TESTING** | Test skills, iterate via evolution loop |
|
|
88
|
+
| **DISTILLATION** | Convert skills to worker LLM workflows |
|
|
89
|
+
| **PRODUCTION_QC** | Run workflows on production docs with QC |
|
|
90
|
+
|
|
91
|
+
## Slash Commands
|
|
92
|
+
|
|
93
|
+
| Command | Description |
|
|
94
|
+
|---------|-------------|
|
|
95
|
+
| `/help` | Show available commands |
|
|
96
|
+
| `/status` | Session info, model, phase, context usage |
|
|
97
|
+
| `/clear` | Clear conversation history |
|
|
98
|
+
| `/compact` | Summarize older messages to reduce context usage |
|
|
99
|
+
| `/sessions` | List all sessions |
|
|
100
|
+
| `/resume <name>` | Resume a previous session (restores phase + pipeline state) |
|
|
101
|
+
| `/rename <name>` | Rename current session |
|
|
102
|
+
| `/exit` | Save state and quit |
|
|
103
|
+
|
|
104
|
+
## Keyboard Shortcuts
|
|
105
|
+
|
|
106
|
+
- **Enter** — Send message
|
|
107
|
+
- **Ctrl+C** — Clear queue (if streaming) or save & exit
|
|
108
|
+
- **Ctrl+D** — Save & exit
|
|
109
|
+
|
|
110
|
+
## Status Bar
|
|
111
|
+
|
|
112
|
+
The status bar shows:
|
|
113
|
+
- Session ID and current phase
|
|
114
|
+
- **Context usage**: `CTX: 45.2k/200k (23%)` — turns green/yellow/red as context fills
|
|
115
|
+
|
|
116
|
+
## Per-Project Config
|
|
117
|
+
|
|
118
|
+
Override global settings in your project's `.env`:
|
|
119
|
+
|
|
120
|
+
```env
|
|
121
|
+
LLM_API_KEY=sk-xxx
|
|
122
|
+
LLM_BASE_URL=https://api.siliconflow.cn/v1
|
|
123
|
+
|
|
124
|
+
TIER1=Pro/zai-org/GLM-5
|
|
125
|
+
TIER2=
|
|
126
|
+
TIER3=
|
|
127
|
+
TIER4=
|
|
128
|
+
|
|
129
|
+
SKILL_ACCURACY=0.9
|
|
130
|
+
WORKFLOW_ACCURACY=0.9
|
|
131
|
+
MAX_ITERATIONS=20
|
|
132
|
+
|
|
133
|
+
# Optional: web search via Tavily
|
|
134
|
+
TAVILY_API_KEY=tvly-xxx
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Legacy keys (`SILICONFLOW_API_KEY`, `SILICONFLOW_BASE_URL`) are still accepted for backward compatibility.
|
|
138
|
+
|
|
139
|
+
## Web Search
|
|
140
|
+
|
|
141
|
+
KC can search the web using Tavily when information is not available in your provided documents. Set `TAVILY_API_KEY` in your `.env` or global config. KC prioritizes your domain documents over web results.
|
|
142
|
+
|
|
143
|
+
## Troubleshooting
|
|
144
|
+
|
|
145
|
+
- **"No API key configured"** — Run `kc-beta onboard` first
|
|
146
|
+
- **Connection errors** — Check your API key and base URL. KC retries up to 10 times with exponential backoff on transient failures.
|
|
147
|
+
- **Context too long** — Use `/compact` to summarize older messages, or let automatic windowing handle it
|
|
148
|
+
- **Resume after crash** — Use `/resume <session-name>` to pick up where you left off
|
|
149
|
+
- **Node version** — Requires Node.js 20+. Check with `node --version`
|
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# KC Agent CLI (`kc-beta`)
|
|
2
|
+
|
|
3
|
+
> Build, distill, and run document verification systems with an LLM agent.
|
|
4
|
+
> Pure Node.js. One binary. Bring your own model.
|
|
5
|
+
|
|
6
|
+
KC is a coding agent purpose-built for **rule-based document verification**:
|
|
7
|
+
read a regulation, decompose it into atomic verification rules, write skills
|
|
8
|
+
to check each rule against sample documents, and (optionally) distill those
|
|
9
|
+
skills into cheap worker-LLM workflows for production batch processing.
|
|
10
|
+
|
|
11
|
+
It is designed for the developer at a bank, insurer, or law firm who needs
|
|
12
|
+
to verify hundreds of documents against dozens of compliance rules — and
|
|
13
|
+
wants the system to be transparent, testable, and ownable.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g kc-beta
|
|
21
|
+
kc-beta onboard # configure provider + API key
|
|
22
|
+
cd my-project # a folder containing rules/ and samples/
|
|
23
|
+
kc-beta # launch the agent
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Requires **Node.js 20+**. See [QUICKSTART.md](./QUICKSTART.md) for the full setup walkthrough.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## What It Does
|
|
31
|
+
|
|
32
|
+
KC drives a single coding agent through six phases:
|
|
33
|
+
|
|
34
|
+
| Phase | What it does |
|
|
35
|
+
|-------|-------------|
|
|
36
|
+
| **BOOTSTRAP** | Set up the workspace, detect rules/samples in your project |
|
|
37
|
+
| **EXTRACTION** | Decompose regulation documents into atomic, testable rules |
|
|
38
|
+
| **SKILL_AUTHORING** | Write a verification skill for each rule (Anthropic skill-creator format) |
|
|
39
|
+
| **SKILL_TESTING** | Run skills on samples, iterate via the evolution loop |
|
|
40
|
+
| **DISTILLATION** | Convert proven skills into cheap worker-LLM workflows |
|
|
41
|
+
| **PRODUCTION_QC** | Run workflows on production batches with confidence-based sampling |
|
|
42
|
+
|
|
43
|
+
The conductor LLM (your main model) drives all reasoning. Worker LLM tools
|
|
44
|
+
are gated to DISTILL phases only, so the build phase is always grounded in
|
|
45
|
+
high-quality output.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Architecture
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
~/.kc_agent/
|
|
53
|
+
config.json # provider, API key, model tiers
|
|
54
|
+
workspaces/<sessionId>/ # KC's working files
|
|
55
|
+
rules/, rule_skills/, workflows/, samples/, output/, logs/
|
|
56
|
+
AGENT.md # per-project context (KC can edit)
|
|
57
|
+
tasks.json # ralph-loop task list
|
|
58
|
+
session-state.json # phase + pipeline state for /resume
|
|
59
|
+
|
|
60
|
+
your-project/ # where you launched kc-beta
|
|
61
|
+
rules/ # source regulations (KC reads with scope="project")
|
|
62
|
+
samples/ # sample documents
|
|
63
|
+
Output/ # KC writes user-facing reports here
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Dual-directory design.** KC has full read/write to its own workspace plus
|
|
67
|
+
*scoped* read/write to your project directory. Source files stay in your
|
|
68
|
+
project; KC's working artifacts stay in `~/.kc_agent/workspaces/`.
|
|
69
|
+
|
|
70
|
+
**Phase-gated tools.** Worker LLM, workflow runner, tier downgrade, and QC
|
|
71
|
+
sampling tools only register during DISTILL phases. BUILD phases force the
|
|
72
|
+
conductor to do the intellectual work directly — the results are the
|
|
73
|
+
ground-truth baseline for distillation.
|
|
74
|
+
|
|
75
|
+
**Skills as first-class deliverables.** Every rule produces a self-contained
|
|
76
|
+
skill folder (SKILL.md + scripts + references + samples). For complex rules
|
|
77
|
+
that worker LLMs can't reliably handle, the skill itself — run by a capable
|
|
78
|
+
agent — is the production solution.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Provider Support
|
|
83
|
+
|
|
84
|
+
10 providers configured out of the box:
|
|
85
|
+
|
|
86
|
+
- **SiliconFlow** (default, recommended for China)
|
|
87
|
+
- **Aliyun Bailian** (with coding-plan key support)
|
|
88
|
+
- **VolcanoCloud** (ByteDance Doubao)
|
|
89
|
+
- **Anthropic** (Messages API native)
|
|
90
|
+
- **OpenAI**
|
|
91
|
+
- **Zhipu GLM**
|
|
92
|
+
- **MiniMax**
|
|
93
|
+
- **OpenRouter**
|
|
94
|
+
- **AWS Bedrock** (stub)
|
|
95
|
+
- **Custom** (any OpenAI-compatible endpoint)
|
|
96
|
+
|
|
97
|
+
Model assignments live in [`src/model-tiers.json`](./src/model-tiers.json) —
|
|
98
|
+
edit directly to update tier-1 through tier-4 LLM and tier-1 through tier-3
|
|
99
|
+
VLM (vision) models per provider, no code changes needed.
|
|
100
|
+
|
|
101
|
+
You can use **separate providers** for the conductor and worker LLMs (e.g.,
|
|
102
|
+
Anthropic conductor + SiliconFlow workers).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Ralph-Loop Autonomous Execution
|
|
107
|
+
|
|
108
|
+
When KC extracts rules, it automatically generates a per-rule task list and
|
|
109
|
+
processes them one at a time. Between tasks the conductor's context is
|
|
110
|
+
compacted aggressively, so context stays bounded even with 50+ rules.
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
SKILL_AUTHORING [████████░░░░] 8/12
|
|
114
|
+
✓ R001 Registered capital check
|
|
115
|
+
✓ R002 Net asset adequacy
|
|
116
|
+
▸ R003 Related-party disclosure ← current
|
|
117
|
+
· R004 Risk capital calculation
|
|
118
|
+
...
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Use `/tasks` to see the full list. The agent decides *how* to do each task;
|
|
122
|
+
the task manager only tells it *what's next*.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Slash Commands
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
/help Show available commands
|
|
130
|
+
/status Session, model, phase, context usage
|
|
131
|
+
/tasks Show task list and progress
|
|
132
|
+
/clear Clear conversation (workspace preserved)
|
|
133
|
+
/compact Summarize older messages via the conductor
|
|
134
|
+
/sessions List all sessions
|
|
135
|
+
/resume <name> Resume a previous session
|
|
136
|
+
/rename <name> Rename current session
|
|
137
|
+
/exit Save state and quit
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`--en` / `--zh` flags override language for one session without writing config.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Optional Plugins
|
|
145
|
+
|
|
146
|
+
Some heavyweight features ship as **meta-meta skills** the agent invokes on
|
|
147
|
+
demand, rather than always-on dependencies:
|
|
148
|
+
|
|
149
|
+
- **`pdf-review-dashboard`** — Two-column HTML dashboard (PDF on the left,
|
|
150
|
+
verification results on the right, click-to-jump) for manual review and
|
|
151
|
+
ground-truth collection.
|
|
152
|
+
- **`auto-model-selection`** — Use [Context7](https://github.com/upstash/context7)
|
|
153
|
+
CLI to fetch current model listings when the bundled `model-tiers.json`
|
|
154
|
+
is stale or you've switched providers.
|
|
155
|
+
|
|
156
|
+
Both are bundled in `template/skills/{en,zh}/meta-meta/` and discovered by
|
|
157
|
+
the skill loader at startup.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Configuration
|
|
162
|
+
|
|
163
|
+
Global config: `~/.kc_agent/config.json` (set by `kc-beta onboard`).
|
|
164
|
+
Per-project override: `<project>/.env`.
|
|
165
|
+
|
|
166
|
+
Edit anytime with the category-based editor:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
kc-beta config
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Categories: LLM Provider, Model Tiers, VLM Tiers, Worker LLM Provider,
|
|
173
|
+
Quality Thresholds, Language.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Documentation
|
|
178
|
+
|
|
179
|
+
- [QUICKSTART.md](./QUICKSTART.md) — full setup and slash command reference
|
|
180
|
+
- [DEV_LOG.md](./DEV_LOG.md) — release history and design rationale
|
|
181
|
+
- [docs/global_update_design_v3.md](./docs/global_update_design_v3.md) — v3 design plan and progress tracker
|
|
182
|
+
- [docs/initial_spec_draft.md](./docs/initial_spec_draft.md) — original architectural spec
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Status
|
|
187
|
+
|
|
188
|
+
**v0.3.1 — beta.** Production-readiness update covering the seven blocks
|
|
189
|
+
of the v3 design plan: dual-directory permissions, AGENT.md per-project
|
|
190
|
+
context, PDF review dashboard skill, parsing/extraction skill rewrites,
|
|
191
|
+
production-experience meta-skill polish, model-tier baseline + Context7
|
|
192
|
+
plugin, and ralph-loop autonomous task execution.
|
|
193
|
+
|
|
194
|
+
We are inviting a small group of developer users to test before public launch.
|
|
195
|
+
Bug reports and PRs welcome at <https://github.com/kitchen-engineer42/kc-cli>.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT. Bundled meta-skills under `template/skills/` are proprietary —
|
|
202
|
+
distributed via npm but not open-source. See `template/skills/LICENSE` for
|
|
203
|
+
terms.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
*Built by Memium / kitchen-engineer42.*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kc-beta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "KC Agent — LLM document verification agent (pure Node.js CLI)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,8 +9,18 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
11
|
"src/",
|
|
12
|
-
"template/"
|
|
12
|
+
"template/",
|
|
13
|
+
"README.md",
|
|
14
|
+
"QUICKSTART.md"
|
|
13
15
|
],
|
|
16
|
+
"homepage": "https://github.com/kitchen-engineer42/kc-cli",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/kitchen-engineer42/kc-cli.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/kitchen-engineer42/kc-cli/issues"
|
|
23
|
+
},
|
|
14
24
|
"engines": {
|
|
15
25
|
"node": ">=20.0.0"
|
|
16
26
|
},
|
package/src/agent/context.js
CHANGED
|
@@ -32,9 +32,11 @@ outcome. Handle ambiguity explicitly — note it, ask the developer user. After
|
|
|
32
32
|
audit which regulation sections are not yet covered.
|
|
33
33
|
|
|
34
34
|
### Entity Extraction
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
Choose the cheapest method that meets accuracy threshold. Regex is the smallest \
|
|
36
|
+
"model" — zero cost, instant, deterministic. Worker LLM handles semantic tasks \
|
|
37
|
+
regex cannot (contextual interpretation, misleading language, adequacy judgment). \
|
|
38
|
+
Try different methods, find the cost-accuracy balance. Every extraction captures: \
|
|
39
|
+
value, evidence, source location, confidence, method used.
|
|
38
40
|
|
|
39
41
|
### Skill Authoring
|
|
40
42
|
Write each rule into a skill folder following the Anthropic skill-creator format. A \
|
|
@@ -79,13 +81,15 @@ unclear regulations with them. Present results and let them judge.`;
|
|
|
79
81
|
export class ContextAssembler {
|
|
80
82
|
/**
|
|
81
83
|
* @param {object} [opts]
|
|
84
|
+
* @param {string} [opts.agentMd] - Content of workspace AGENT.md (per-project context)
|
|
82
85
|
* @param {string} [opts.pipelineState]
|
|
83
86
|
* @param {string} [opts.workspaceState]
|
|
84
87
|
* @param {string} [opts.skillIndex] - Brief index of available meta skills
|
|
85
88
|
* @returns {string}
|
|
86
89
|
*/
|
|
87
|
-
build({ pipelineState, workspaceState, skillIndex } = {}) {
|
|
90
|
+
build({ agentMd, pipelineState, workspaceState, skillIndex } = {}) {
|
|
88
91
|
const parts = [AGENT_IDENTITY];
|
|
92
|
+
if (agentMd) parts.push(agentMd);
|
|
89
93
|
if (skillIndex) parts.push(skillIndex);
|
|
90
94
|
if (pipelineState) parts.push(pipelineState);
|
|
91
95
|
if (workspaceState) parts.push(workspaceState);
|
package/src/agent/engine.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import { AgentEvent } from "./events.js";
|
|
2
4
|
import { ContextAssembler } from "./context.js";
|
|
3
5
|
import { ConversationHistory } from "./history.js";
|
|
@@ -20,6 +22,7 @@ import { TierDowngradeTool } from "./tools/tier-downgrade.js";
|
|
|
20
22
|
import { AgentTool } from "./tools/agent-tool.js";
|
|
21
23
|
import { WebSearchTool } from "./tools/web-search.js";
|
|
22
24
|
import { SkillLoader } from "./skill-loader.js";
|
|
25
|
+
import { TaskManager } from "./task-manager.js";
|
|
23
26
|
import { Phase } from "./pipelines/index.js";
|
|
24
27
|
import { ProjectInitializer } from "./pipelines/initializer.js";
|
|
25
28
|
import { RuleExtractionPipeline } from "./pipelines/extraction.js";
|
|
@@ -56,7 +59,7 @@ export class AgentEngine {
|
|
|
56
59
|
this.context = new ContextAssembler();
|
|
57
60
|
|
|
58
61
|
// Workspace + structural components
|
|
59
|
-
this.workspace = new Workspace(config.kcWorkspaceRoot, sessionId);
|
|
62
|
+
this.workspace = new Workspace(config.kcWorkspaceRoot, sessionId, config.projectDir);
|
|
60
63
|
this.history = new ConversationHistory(this.workspace.cwd);
|
|
61
64
|
this.versionManager = new VersionManager(this.workspace.cwd);
|
|
62
65
|
this.cornerCases = new CornerCaseRegistry(this.workspace.cwd);
|
|
@@ -74,6 +77,9 @@ export class AgentEngine {
|
|
|
74
77
|
// Session state persistence
|
|
75
78
|
this.sessionState = new SessionState(this.workspace.cwd);
|
|
76
79
|
|
|
80
|
+
// Task manager (ralph-loop)
|
|
81
|
+
this.taskManager = new TaskManager(this.workspace.cwd);
|
|
82
|
+
|
|
77
83
|
// Build all tool instances (but register phase-appropriate ones)
|
|
78
84
|
this._buildTools = this._createAllTools();
|
|
79
85
|
this._phaseSummaries = [];
|
|
@@ -102,12 +108,20 @@ export class AgentEngine {
|
|
|
102
108
|
* re-register per phase without recreating.
|
|
103
109
|
*/
|
|
104
110
|
_createAllTools() {
|
|
111
|
+
// Worker LLM uses separate config if set, otherwise falls back to conductor
|
|
112
|
+
const workerApiKey = this.config.effectiveWorkerApiKey();
|
|
113
|
+
const workerBaseUrl = this.config.effectiveWorkerBaseUrl();
|
|
114
|
+
const workerAuthType = this.config.effectiveWorkerAuthType();
|
|
115
|
+
|
|
105
116
|
const workerLlm = new WorkerLLMCallTool(this.workspace, {
|
|
106
|
-
apiKey:
|
|
107
|
-
baseUrl:
|
|
108
|
-
authType:
|
|
117
|
+
apiKey: workerApiKey,
|
|
118
|
+
baseUrl: workerBaseUrl,
|
|
119
|
+
authType: workerAuthType,
|
|
109
120
|
});
|
|
110
121
|
|
|
122
|
+
// OCR/VLM uses worker config (VLM is a type of worker LLM)
|
|
123
|
+
const vlmModel = this.config.vlmTier1 || "";
|
|
124
|
+
|
|
111
125
|
return {
|
|
112
126
|
// Always available (BUILD + DISTILL)
|
|
113
127
|
core: [
|
|
@@ -116,9 +130,9 @@ export class AgentEngine {
|
|
|
116
130
|
new DocumentParseTool(this.workspace, {
|
|
117
131
|
mineruApiUrl: this.config.mineruApiUrl,
|
|
118
132
|
mineruApiKey: this.config.mineruApiKey,
|
|
119
|
-
llmApiKey:
|
|
120
|
-
llmBaseUrl:
|
|
121
|
-
ocrModel:
|
|
133
|
+
llmApiKey: workerApiKey,
|
|
134
|
+
llmBaseUrl: workerBaseUrl,
|
|
135
|
+
ocrModel: vlmModel,
|
|
122
136
|
}),
|
|
123
137
|
new DocumentSearchTool(this.workspace),
|
|
124
138
|
new RuleCatalogTool(this.workspace),
|
|
@@ -156,15 +170,57 @@ export class AgentEngine {
|
|
|
156
170
|
}
|
|
157
171
|
}
|
|
158
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Read AGENT.md from workspace (per-project context).
|
|
175
|
+
* Returns content string or empty string if not found.
|
|
176
|
+
*/
|
|
177
|
+
_readAgentMd() {
|
|
178
|
+
const agentMdPath = path.join(this.workspace.cwd, "AGENT.md");
|
|
179
|
+
try {
|
|
180
|
+
if (fs.existsSync(agentMdPath)) {
|
|
181
|
+
return fs.readFileSync(agentMdPath, "utf-8");
|
|
182
|
+
}
|
|
183
|
+
} catch { /* ignore */ }
|
|
184
|
+
return "";
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Build the workspace/project directory state string for the system prompt.
|
|
189
|
+
*/
|
|
190
|
+
_buildWorkspaceState() {
|
|
191
|
+
const lines = [
|
|
192
|
+
`## Directory Layout`,
|
|
193
|
+
`**KC Workspace:** ${this.workspace.cwd}`,
|
|
194
|
+
` Use scope="workspace" (default). Write all working files here (rules, skills, workflows, results, logs).`,
|
|
195
|
+
];
|
|
196
|
+
if (this.workspace.projectDir) {
|
|
197
|
+
lines.push(
|
|
198
|
+
`**Project Directory:** ${this.workspace.projectDir}`,
|
|
199
|
+
` Use scope="project" to read/write files in the user's project folder.`,
|
|
200
|
+
` This is where the user's source regulations, samples, and reference documents are.`,
|
|
201
|
+
``,
|
|
202
|
+
`Read source documents from the project directory. Write KC outputs to the workspace.`,
|
|
203
|
+
`Write user-facing exports (reports, results) to the project directory when the user asks.`,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Task progress (ralph-loop)
|
|
208
|
+
const taskContext = this.taskManager.describeForContext();
|
|
209
|
+
if (taskContext) lines.push("", taskContext);
|
|
210
|
+
|
|
211
|
+
return lines.join("\n");
|
|
212
|
+
}
|
|
213
|
+
|
|
159
214
|
/**
|
|
160
215
|
* Get current context usage statistics.
|
|
161
216
|
* @returns {{ totalTokens: number, limit: number, percentage: number }}
|
|
162
217
|
*/
|
|
163
218
|
getContextStats() {
|
|
164
219
|
const systemPrompt = this.context.build({
|
|
220
|
+
agentMd: this._readAgentMd(),
|
|
165
221
|
skillIndex: this._skillLoader.formatForContext(),
|
|
166
222
|
pipelineState: this.pipelines[this.currentPhase]?.describeState?.() || null,
|
|
167
|
-
workspaceState:
|
|
223
|
+
workspaceState: this._buildWorkspaceState(),
|
|
168
224
|
});
|
|
169
225
|
const systemTokens = estimateTokens(systemPrompt);
|
|
170
226
|
const messageTokens = estimateMessagesTokens(this.history.messages);
|
|
@@ -270,6 +326,14 @@ export class AgentEngine {
|
|
|
270
326
|
engine._phaseSummaries = data.phaseSummaries || [];
|
|
271
327
|
engine._registerToolsForPhase(engine.currentPhase);
|
|
272
328
|
|
|
329
|
+
// Restore project directory from saved state
|
|
330
|
+
if (data.projectDir) {
|
|
331
|
+
if (fs.existsSync(data.projectDir)) {
|
|
332
|
+
engine.workspace.projectDir = data.projectDir;
|
|
333
|
+
}
|
|
334
|
+
// If dir no longer exists, projectDir stays as whatever was passed at launch
|
|
335
|
+
}
|
|
336
|
+
|
|
273
337
|
// Restore pipeline milestones
|
|
274
338
|
const milestones = data.pipelineMilestones || {};
|
|
275
339
|
for (const [phase, mData] of Object.entries(milestones)) {
|
|
@@ -309,9 +373,10 @@ export class AgentEngine {
|
|
|
309
373
|
const pipelineState = pipeline?.describeState?.() || null;
|
|
310
374
|
|
|
311
375
|
const systemPrompt = this.context.build({
|
|
376
|
+
agentMd: this._readAgentMd(),
|
|
312
377
|
skillIndex: this._skillLoader.formatForContext(),
|
|
313
378
|
pipelineState,
|
|
314
|
-
workspaceState:
|
|
379
|
+
workspaceState: this._buildWorkspaceState(),
|
|
315
380
|
});
|
|
316
381
|
const tools = this.toolRegistry.schemasOpenai();
|
|
317
382
|
|
|
@@ -433,6 +498,10 @@ export class AgentEngine {
|
|
|
433
498
|
});
|
|
434
499
|
this.currentPhase = pEvent.nextPhase;
|
|
435
500
|
this._registerToolsForPhase(this.currentPhase);
|
|
501
|
+
|
|
502
|
+
// Ralph-loop: create per-rule tasks for the new phase
|
|
503
|
+
this._createTasksForPhase(this.currentPhase);
|
|
504
|
+
|
|
436
505
|
this.saveState();
|
|
437
506
|
}
|
|
438
507
|
yield new AgentEvent({
|
|
@@ -450,4 +519,80 @@ export class AgentEngine {
|
|
|
450
519
|
}
|
|
451
520
|
}
|
|
452
521
|
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Create per-rule tasks when entering a new phase.
|
|
525
|
+
* Reads the rule catalog and creates one task per rule for the given phase.
|
|
526
|
+
*/
|
|
527
|
+
_createTasksForPhase(phase) {
|
|
528
|
+
const catalogPath = path.join(this.workspace.cwd, "rules", "catalog.json");
|
|
529
|
+
if (!fs.existsSync(catalogPath)) return;
|
|
530
|
+
|
|
531
|
+
try {
|
|
532
|
+
const catalog = JSON.parse(fs.readFileSync(catalogPath, "utf-8"));
|
|
533
|
+
const rules = Array.isArray(catalog) ? catalog : [];
|
|
534
|
+
if (rules.length > 0) {
|
|
535
|
+
this.taskManager.createRuleTasks(rules, phase);
|
|
536
|
+
}
|
|
537
|
+
} catch { /* skip if catalog can't be read */ }
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Ralph-loop: run a turn, then auto-continue through pending tasks.
|
|
542
|
+
* Compacts context aggressively between tasks to prevent context blowup.
|
|
543
|
+
* If no tasks exist, behaves identically to runTurn().
|
|
544
|
+
*
|
|
545
|
+
* @param {string} userMessage
|
|
546
|
+
* @yields {AgentEvent}
|
|
547
|
+
*/
|
|
548
|
+
async *runTaskLoop(userMessage) {
|
|
549
|
+
// Run the initial turn (user's request)
|
|
550
|
+
yield* this.runTurn(userMessage);
|
|
551
|
+
|
|
552
|
+
// Auto-continue through pending tasks
|
|
553
|
+
while (this.taskManager.getNextPending()) {
|
|
554
|
+
// Context safety: force compaction if above 70%, or light compaction if history is long
|
|
555
|
+
const stats = this.getContextStats();
|
|
556
|
+
if (stats.percentage > 70) {
|
|
557
|
+
await this.compact();
|
|
558
|
+
} else if (this.history.messages.length > 15) {
|
|
559
|
+
await this.compact({ recentCount: 8 });
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
const task = this.taskManager.getNextPending();
|
|
563
|
+
this.taskManager.updateTask(task.id, { status: "in_progress" });
|
|
564
|
+
|
|
565
|
+
// Yield task progress event for TUI
|
|
566
|
+
yield new AgentEvent({
|
|
567
|
+
type: "task_progress",
|
|
568
|
+
data: {
|
|
569
|
+
taskId: task.id,
|
|
570
|
+
title: task.title,
|
|
571
|
+
ruleId: task.ruleId,
|
|
572
|
+
status: "in_progress",
|
|
573
|
+
progress: this.taskManager.progress,
|
|
574
|
+
},
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
// Synthesize a task-focused prompt
|
|
578
|
+
const taskPrompt = `Continue with next task: ${task.title}` +
|
|
579
|
+
(task.ruleId ? ` (rule: ${task.ruleId})` : "");
|
|
580
|
+
|
|
581
|
+
yield* this.runTurn(taskPrompt);
|
|
582
|
+
|
|
583
|
+
this.taskManager.updateTask(task.id, { status: "completed" });
|
|
584
|
+
this.taskManager.save();
|
|
585
|
+
this.saveState();
|
|
586
|
+
|
|
587
|
+
yield new AgentEvent({
|
|
588
|
+
type: "task_progress",
|
|
589
|
+
data: {
|
|
590
|
+
taskId: task.id,
|
|
591
|
+
title: task.title,
|
|
592
|
+
status: "completed",
|
|
593
|
+
progress: this.taskManager.progress,
|
|
594
|
+
},
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
453
598
|
}
|