M1 core: tool trait, permission service, config, Provider trait, engine loop

harness-core now has everything the headless agent loop needs:
- Tool trait/ToolCtx/ToolRegistry + 30k-char head+tail output truncation
- PermissionService: async ask over a oneshot + AppEvent::PermissionAsked,
  Once/Always/Reject replies, an auto-approve stub for tests/headless runs
- Config: JSONC loading, bundled/global/project-chain/env precedence,
  {env:VAR} and {file:path} interpolation
- llm.rs: LlmEvent/LlmRequest/Provider trait, wire message/content types
- engine/: outer loop (run_session), inner stream processor (persists
  parts/messages as events arrive, executes tool calls inline), retry
  policy (retries only the pre-first-event window), doom-loop guard,
  system prompt assembly

Verified end-to-end against a scripted MockProvider: text -> tool call
(read) -> final text, with messages/parts persisted in the right shape,
plus a provider-error-before-any-event case surfacing as Errored (no
partial message left behind). 49 tests passing, clippy clean.
This commit is contained in:
Erik Simon
2026-07-08 17:05:37 +02:00
parent 5662b773b0
commit a68ca02894
19 changed files with 2933 additions and 10 deletions
+3
View File
@@ -57,6 +57,9 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tracing-appender = "0.2"
dirs = "5"
shell-words = "1"
tempfile = "3"
insta = "1"
wiremock = "0.6"
[workspace.lints.rust]
unsafe_code = "deny"