Sets up the Cargo workspace (harness-core, harness-tools, harness-providers, harness-mcp, harness-lsp, harness-app, harness-tui) and the ten architecture docs under docs/. harness-core gets its foundational types (session/message/part/model ids), an in-process event bus, a table-driven permission evaluate function, and a SQLite-backed storage actor with schema and roundtrip coverage. Every crate compiles empty and a bin stub prints its version.
66 lines
3.0 KiB
Markdown
66 lines
3.0 KiB
Markdown
# 06 — Config System
|
|
|
|
`harness-core/src/config/`.
|
|
|
|
## Locations & precedence (lowest → highest)
|
|
|
|
1. Bundled defaults (compiled in)
|
|
2. Global: `~/.config/ai-harness/config.json`
|
|
3. Project chain: walk up from cwd collecting `.harness/config.json`, apply root-most first
|
|
4. Env overrides (`AI_HARNESS_MODEL`, `AI_HARNESS_CONFIG`, provider key env vars)
|
|
|
|
JSONC via `jsonc-parser` (comments + trailing commas). Deep-merge objects, replace arrays. After merge: string interpolation of `{env:VAR}` and `{file:path}` (the latter useful for prompts).
|
|
|
|
## Schema
|
|
|
|
```rust
|
|
pub struct Config {
|
|
pub model: Option<String>, // "anthropic/claude-sonnet-4-5"
|
|
pub small_model: Option<String>, // titles/summaries/compaction
|
|
pub providers: HashMap<String, ProviderConfig>, // { enabled, api_key, base_url }
|
|
pub agents: HashMap<String, AgentPatch>, // patch semantics over loaded agent defs
|
|
pub permissions: Vec<Rule>, // ordered; last-match-wins
|
|
pub orchestration: OrchestrationConfig, // { depth_limit: 3, job_board: true,
|
|
// max_reusable_per_agent: 2, reminders: None }
|
|
pub mcp: HashMap<String, McpServerConfig>, // { command, args, env, enabled }
|
|
pub lsp: HashMap<String, LspServerConfig>, // { command, args, extensions: ["rs"] }
|
|
pub tui: TuiConfig, // theme; keybinds later
|
|
pub instructions: Vec<String>, // files appended to system prompt (AGENTS.md, ...)
|
|
}
|
|
|
|
pub struct Rule { pub permission: String, pub pattern: String, pub action: Action }
|
|
```
|
|
|
|
Example:
|
|
|
|
```jsonc
|
|
{
|
|
"model": "github-copilot/claude-sonnet-4.5",
|
|
"small_model": "openai/gpt-4o-mini",
|
|
"providers": {
|
|
"anthropic": { "api_key": "{env:ANTHROPIC_API_KEY}" }
|
|
},
|
|
"agents": {
|
|
"explorer": { "model": "github-copilot/gpt-4o", "temperature": 0 },
|
|
"designer": { "disable": true },
|
|
// unknown key + prompt/model → custom agent
|
|
"reviewer": { "mode": "subagent", "prompt": "{file:./prompts/reviewer.md}" }
|
|
},
|
|
"permissions": [
|
|
{ "permission": "bash", "pattern": "git status*", "action": "allow" },
|
|
{ "permission": "edit", "pattern": "*.lock", "action": "deny" }
|
|
],
|
|
"mcp": {
|
|
"context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] }
|
|
}
|
|
}
|
|
```
|
|
|
|
## Markdown asset loading (`config/markdown.rs`)
|
|
|
|
All three kinds use YAML frontmatter + markdown body, from `~/.config/ai-harness/<kind>/` (global) and `<project>/.harness/<kind>/` (project wins by name):
|
|
|
|
- **Agents** — `agent/*.md` → `AgentDef` (see [04-multiagent.md](04-multiagent.md)).
|
|
- **Commands** — `command/*.md` → `CommandDef { name (filename), description, agent?, model?, template }`. Invoked as `/name args` in the TUI; template substitutes `$ARGUMENTS` / `$1..$9` and becomes the user message, optionally switching agent/model for that run.
|
|
- **Skills** — `skill/<name>/SKILL.md` → advertised (name + description) in a system prompt section; the full body is fetched on demand via the built-in `skill` tool.
|