62 Commits

Author SHA1 Message Date
ac69e2f6d5 feat: streaming conversation responses via Mistral API
- Bump mistralai-client to 1.2.0 (conversation streaming support)
- session.rs: add create_or_append_conversation_streaming() — calls
  Mistral with stream:true, emits TextDelta messages to gRPC client
  as SSE chunks arrive, accumulates into ConversationResponse for
  orchestrator tool loop. Corrupted conversation recovery preserved
- service.rs: session_chat_via_orchestrator uses streaming variant
- gRPC tests: handle Delta and ToolCall in all message loops, loosen
  assertions to test infrastructure (streaming works, tokens counted,
  session resumes) rather than specific LLM output
- Integration tests: streaming create + append against real Mistral
  API, SSE parsing, accumulate text + function calls
2026-03-25 17:14:30 +00:00
261c39b424 feat: streaming conversation responses via Mistral API
- Bump mistralai-client to 1.2.0 (conversation streaming support)
- session.rs: add create_or_append_conversation_streaming() — calls
  Mistral with stream:true, emits TextDelta messages to gRPC client
  as SSE chunks arrive, accumulates into ConversationResponse for
  orchestrator tool loop. Handles corrupted conversation recovery
- service.rs: session_chat_via_orchestrator uses streaming variant
- Integration tests: streaming create + append against real Mistral
  API, SSE parsing, accumulate text + function calls
2026-03-24 21:33:01 +00:00
6a2aafdccc refactor: remove legacy chat path, fix corrupted conversation recovery
- Delete CodeSession::chat() — the legacy inline tool loop that
  duplicated the orchestrator's conversation + tool dispatch logic
- Delete wait_for_tool_result() — only used by the legacy path
- Make orchestrator mandatory in run_session (no more if/else fallback)
- Unify conversation creation into create_fresh_conversation()
- Add corrupted conversation recovery to create_or_append_conversation:
  detects "function calls and responses" errors from Mistral (caused by
  disconnecting mid-tool-call) and auto-creates a fresh conversation
- Add tracing-appender for optional rotating log file (SOL_LOG_FILE env)
- Add Procfile.dev for overmind process management
2026-03-24 19:49:07 +00:00
d58bbfce66 feat: gRPC keepalive — ping/pong handler + HTTP/2 keepalive
- proto: add Ping/Pong message types for application-level keepalive
- service: echo Pong back on Ping in run_session message loop
- mod: configure HTTP/2 keepalive on server builder (15s interval,
  5s timeout) to detect half-open connections
2026-03-24 18:07:02 +00:00
ecf0ead7c7 feat: project symbol extraction integration test
- extract_project_symbols against tempdir with Rust/TypeScript/Python
  sources — walk_directory, detect_language, hidden/vendor dir skipping,
  ProjectSymbol field population, docstring extraction
2026-03-24 17:24:39 +00:00
2a87be9167 feat: conversation active_count test
- verify active_count increments on send_message, decrements on reset
2026-03-24 16:50:32 +00:00
0d83425b17 feat: script sol.rooms/fetch/memory ops + research execute integration
- script: sol.rooms() against live Tuwunel, sol.fetch() with allowlist
  enforcement (allowed domain succeeds, blocked domain caught),
  sol.memory.set/get round-trip against OpenSearch
- research: single-task execute against Mistral API with real Matrix
  room, verifies session persistence lifecycle
2026-03-24 16:34:44 +00:00
2eda81ef2e feat: gitea branch lifecycle tests
- gitea: create_branch, delete_branch, list verification on studio/sol
2026-03-24 16:05:10 +00:00
ef040aae38 feat: conversation registry compaction, reset, context hint tests
- needs_compaction: verify threshold triggers after token accumulation
- set_agent_id / get_agent_id: round-trip agent ID storage
- reset_all: verify all rooms cleared, SQLite and memory
- context_hint: verify conversation receives recent history context
  when creating new conversation with hint parameter
2026-03-24 15:43:50 +00:00
f338444087 feat: matrix room, room_info, research execute, bootstrap improvements
- bootstrap: create integration test room in Tuwunel, send bootstrap
  message, print room ID in summary
- room_info: list_rooms and get_room_members against live Tuwunel
- research: execute with empty tasks against real Matrix room + Mistral
- identity: fix flaky list_users_tool test (use search instead of
  unbounded list to avoid pagination)
2026-03-24 15:38:12 +00:00
b5c83b7c34 feat: gitea SDK extended tests + research type coverage
- gitea: list_org_repos, get_issue, list_notifications, list_orgs,
  get_org — exercises authed_get paths for more API endpoints
- research: empty tasks parse, multiple tasks parse, depth boundary
  edge cases
2026-03-24 15:15:56 +00:00
f1009ddda4 feat: deeper script sandbox and research type tests
- script tool: async operations, sol.fs.list, console.log/error/warn/
  info, return value capture, additional sandbox coverage
- research tool: tool_definition schema validation, depth boundary
  exhaustive testing, ResearchTask/ResearchResult roundtrips,
  output format verification
- matrix_utils: extract_image returns None for text messages
2026-03-24 15:04:39 +00:00
e59b55e6a9 feat: matrix, script, evaluator, and devtools integration tests
- matrix_utils: construct ruma events in tests, verify extract_body
  (text/notice/emote/unsupported), extract_reply_to, extract_thread_id,
  extract_edit, extract_image, make_reply_content, make_thread_reply
- script tool: full run_script against live Tuwunel + OpenSearch —
  basic math, TypeScript transpilation, filesystem sandbox read/write,
  error capture, output truncation, invalid args
- evaluator: DM/mention/silence short-circuits, LLM evaluation path
  with Mistral API, reply-to-human suppression
- agent registry: list/get_id, prompt reuse, prompt-change recreation
- devtools: tool dispatch for list_repos, get_repo, list_issues,
  get_file, list_branches, list_comments, list_orgs
- conversations: token tracking, multi-turn context recall, room
  isolation
2026-03-24 14:48:13 +00:00
5dc739b800 feat: integration test suite — 416 tests, 61% coverage
Add OpenBao and Kratos to docker-compose dev stack with bootstrap
seeding. Full integration tests hitting real services:

- Vault SDK: KV read/write/delete, re-auth on bad token, new_with_token
  constructor for dev mode
- Kratos SDK: list/get/create/disable/enable users, session listing
- Token store: PAT lifecycle with OpenBao backing, expiry handling
- Identity tools: full tool dispatch through Kratos admin API
- Gitea SDK: resolve_username, ensure_token (PAT auto-provisioning),
  list/get repos, issues, comments, branches, file content
- Devtools: tool dispatch for all gitea_* tools against live Gitea
- Archive indexer: batch flush, periodic flush task, edit/redact/reaction
  updates against OpenSearch
- Memory store: set/query/get_recent with user scoping in OpenSearch
- Room history: context retrieval by timestamp and event_id, access
  control enforcement
- Search archive: keyword search with room/sender filters, room scoping
- Code search: language filter, repo filter, branch scoping
- Breadcrumbs: symbol retrieval, empty index handling, token budget
- Bridge: full event lifecycle mapping, request ID filtering
- Evaluator: DM/mention/silence short-circuits, LLM evaluation path,
  reply-to-human suppression
- Agent registry: list/get_id, prompt reuse, prompt-change recreation
- Conversations: token tracking, multi-turn context recall, room
  isolation

Bug fixes caught by tests:
- AgentRegistry in-memory cache skipped hash comparison on prompt change
- KratosClient::set_state sent bare PUT without traits (400 error)
- find_code_session returns None on NULL conversation_id
2026-03-24 14:34:03 +00:00
b3a38767e0 docs: update CLAUDE.md, deployment, and conversations docs
CLAUDE.md: updated source layout with orchestrator, grpc, code_index,
breadcrumbs modules. Deployment: added gRPC service, startup flowchart,
new secrets and troubleshooting. Conversations: updated lifecycle to
show orchestrator path and gRPC session keys.
2026-03-24 12:58:35 +00:00
2949ea354f docs: comprehensive README rewrite — orchestrator, gRPC, code indexing, new tools
Cover the transport-agnostic orchestrator, gRPC CodeAgent service,
tree-sitter code indexing, client/server tool dispatch, research tool,
SearXNG web search, Kratos identity tools, breadcrumbs, and all new
config sections.
2026-03-24 12:58:18 +00:00
4528739a5f feat: deterministic Gitea integration tests + mutation lifecycle
Bootstrap:
- Creates test issue + comment on studio/sol for deterministic test data
- Mirrors 6 real repos from src.sunbeam.pt

Devtools tests (13, all deterministic):
- Read: list_repos, get_repo, get_file, list_branches, list_issues,
  list_pulls, list_comments, list_notifications, list_org_repos,
  get_org, unknown_tool
- Mutation lifecycle: create_repo → create_issue → create_comment →
  create_branch → create_pull → get_pull → edit_issue →
  delete_branch → cleanup (all arg names verified against tool impls)

Additional tests:
- Script sandbox: basic math, string manipulation, JSON output
- Archive search: arg parsing, OpenSearch query
- Persistence: agent CRUD, service user CRUD
- gRPC bridge: event filtering, tool mapping
2026-03-24 12:45:01 +00:00
0efd3e32c3 feat: devtools + tool dispatch tests, search_code tool definition fix
Devtools integration tests (6 new, all via live Gitea):
- gitea_list_repos, get_repo, get_file, list_branches, list_issues, list_orgs
- Tests exercise the full Gitea SDK → tool handler → JSON response path

Tool dispatch tests (8 new unit tests):
- tool_definitions: base, gitea, kratos, all-enabled variants
- agent_tool_definitions conversion
- minimal registry creation
- unknown tool error handling
- search_code without OpenSearch error

search_code: added to tool_definitions() (was only in execute dispatch)
2026-03-24 12:06:39 +00:00
42f6b38f12 feat: comprehensive tool + Gitea + bridge tests, search_code tool definition
Tools module:
- Added search_code to tool_definitions() (was in execute but not defined)
- 8 new unit tests: tool definitions (base/gitea/kratos/all), agent tools,
  minimal registry, unknown tool dispatch, search_code without OpenSearch

Gitea indexer fix:
- Direct API calls for directory listings (SDK parses as single object)
- PAT-based auth for file fetching
- GiteaClient.base_url made public for direct API access

Integration tests:
- Gitea SDK: list_repos, get_repo, get_file, directory, full code indexing
- gRPC bridge: thinking events, tool call mapping, request ID filtering
- Evaluator: rule matching, conversation registry lifecycle
- Web search: SearXNG round-trip
2026-03-24 11:58:01 +00:00
495c465a01 refactor: remove legacy responder + agent_ux, add Gitea integration tests
Legacy removal:
- DELETE src/brain/responder.rs (900 lines) — replaced by orchestrator
- DELETE src/agent_ux.rs (184 lines) — UX moved to transport bridges
- EXTRACT chat_blocking() to src/brain/chat.rs (standalone utility)
- sync.rs: uses ConversationRegistry directly (no responder)
- main.rs: holds ToolRegistry + Personality directly (no Responder wrapper)
- research.rs: progress updates via tracing (no AgentProgress)

Gitea integration testing:
- docker-compose: added Gitea service with healthcheck
- bootstrap-gitea.sh: creates admin, org, mirrors 6 real repos from
  src.sunbeam.pt (sol, cli, proxy, storybook, admin-ui, mistralai-client-rs)
- PAT provisioning for SDK testing without Vault
- code_index/gitea.rs: fixed directory listing (direct API calls instead
  of SDK's single-object parser), proper base64 file decoding

New integration tests:
- Gitea: list_repos, get_repo, get_file, directory listing, code indexing
- Web search: SearXNG query with result verification
- Conversation registry: lifecycle + send_message round-trip
- Evaluator: rule matching (DM, own message)
- gRPC bridge: event filtering, tool call mapping, thinking→status
2026-03-24 11:45:43 +00:00
ec55984fd8 feat: Phase 5 polish — conditional LSP tools, capabilities, sidecar hooks
- ToolSide enum: documented Sidecar future variant
- StartSession.capabilities: client reports LSP availability
- Client detects LSP binaries on PATH, sends ["lsp_rust", "lsp_typescript"]
- build_tool_definitions() conditionally registers LSP tools only when
  client has LSP capability — model won't hallucinate unavailable tools
- CodeSession stores capabilities, has_lsp(), has_capability() accessors
- git_branch() reads from git for breadcrumb scoping
- ToolRegistry.gitea_client() accessor for reindex endpoint
2026-03-24 09:54:14 +00:00
a11b313301 feat: Gitea repo indexing via gRPC ReindexCode endpoint
Gitea indexer (code_index/gitea.rs):
- Walks repos via GiteaClient API (list repos → traverse dirs → fetch files)
- Base64 decodes file content from Gitea API responses
- Extracts symbols with tree-sitter (Rust, TypeScript, Python)
- Indexes to sol_code OpenSearch index with repo/branch/source metadata
- Skips hidden dirs, vendor, node_modules, files >100KB
- delete_branch() for clean re-indexing

Server-side tree-sitter (code_index/symbols.rs):
- Full symbol extraction shared with CLI client
- extract_symbols(), extract_project_symbols(), detect_language()

gRPC ReindexCode RPC:
- ReindexCodeRequest: org, repo, branch (all optional filters)
- ReindexCodeResponse: repos_indexed, symbols_indexed, error
- Uses ToolRegistry's GiteaClient (already authenticated)
- Creates sol_code index if not exists

ToolRegistry.gitea_client() accessor for reindex endpoint.
2026-03-24 09:36:42 +00:00
4d5b3a9b28 feat(tools): register 5 LSP tools as client-side with schemas
- lsp_definition, lsp_references, lsp_hover, lsp_diagnostics, lsp_symbols
  added to CLIENT_TOOLS in tool_dispatch.rs
- Tool schemas added to build_tool_definitions() for Mistral conversations
- LSP tools use path/line/column/query parameters
2026-03-24 00:58:24 +00:00
c6d11259a9 feat(grpc): handle IndexSymbols from client, index to OpenSearch
When client sends IndexSymbols after session start, Sol indexes
the symbols to the sol_code OpenSearch index. Each symbol becomes
a SymbolDocument with file_path, name, kind, signature, docstring,
branch, and source="local".
2026-03-24 00:41:30 +00:00
c213d74620 feat: code search tool + breadcrumb context injection + integration tests
search_code tool:
- Server-side tool querying sol_code OpenSearch index
- BM25 search across symbol_name, signature, docstring, content
- Branch-aware with boost for current branch, mainline fallback
- Registered in ToolRegistry execute dispatch

Breadcrumb injection:
- build_context_header() now async, injects adaptive breadcrumbs
- Hybrid search: _analyze → wildcard symbol matching → BM25
- Token budget enforcement (default outline + relevant expansion)
- Graceful degradation when OpenSearch unavailable

GrpcState:
- Added Option<OpenSearch> for breadcrumb retrieval
- code_index_name() accessor

Integration tests (6 new, 226 total):
- Index + search: bulk index symbols, verify BM25 retrieval
- Breadcrumb outline: aggregation query returns project structure
- Breadcrumb expansion: substantive query triggers relevant symbols
- Token budget: respects character limit
- Branch scoping: feat/code symbols preferred over mainline
- Branch deletion: cleanup removes branch symbols, mainline survives
2026-03-24 00:19:17 +00:00
57f8d608a5 feat: code index + adaptive breadcrumbs foundation
Code index (sol_code):
- SymbolDocument: file_path, repo_name, language, symbol_name, symbol_kind,
  signature, docstring, branch, source, embedding (768-dim knn_vector)
- CodeIndexer: batch symbol indexer with idempotent upserts
- Branch-aware: symbols scoped to branch with mainline fallback

Breadcrumbs:
- build_breadcrumbs(): adaptive context injection for coding prompts
- Default: project outline via aggregation (modules, types, fns)
- Adaptive: hybrid search (_analyze → symbol matching → BM25 + neural)
- Token budget enforcement with priority (outline first, then relevance)
- format_symbol(): signature + first-line docstring + file:line

Query optimization: uses _analyze API to extract key terms from
free-form user text, matches against actual symbol names in the index
before running the hybrid search.
2026-03-23 23:54:29 +00:00
40a6772f99 feat: 13 e2e integration tests against real Mistral API
Orchestrator tests:
- Simple chat roundtrip with token usage verification
- Event ordering (Started → Thinking → Done)
- Metadata pass-through (opaque bag appears in Started event)
- Token usage accuracy (longer prompts → more tokens)
- Conversation continuity (multi-turn recall)
- Client-side tool dispatch + mock result submission
- Failed tool result handling (is_error: true)
- Server-side tool execution (search_web via conversation)

gRPC tests:
- Full roundtrip (StartSession → UserInput → Status → TextDone)
- Client tool relay (ToolCall → ToolResult through gRPC stream)
- Token counts in TextDone (non-zero verification)
- Session resume (same room_id, resumed flag)
- Clean disconnect (EndSession → SessionEnd)

Infrastructure:
- ToolRegistry::new_minimal() — no OpenSearch/Matrix needed
- ToolRegistry fields now Option for testability
- GrpcState.matrix now Option
- grpc_bridge moved to src/grpc/bridge.rs
- TestHarness loads API key from .env
2026-03-23 20:54:28 +00:00
2810143f76 feat(grpc): proper tool result relay via tokio::select
session_chat_via_orchestrator now:
- Spawns generation on a background task
- Reads in_stream for client tool results in foreground
- Forwards results to orchestrator.submit_tool_result()
- Uses tokio::select! to handle both concurrently
- Uses GenerateRequest + Metadata (no transport types in orchestrator)
- Calls grpc::bridge (not orchestrator::grpc_bridge)
2026-03-23 19:23:51 +00:00
a07be70154 refactor(tools): add execute_with_context() for ToolContext
ToolRegistry gains execute_with_context(&ToolContext) which bridges
to the existing execute(&ResponseContext) via a shim. The orchestrator
calls only the new method — no ResponseContext in its dependency tree.
2026-03-23 19:23:36 +00:00
64facb3344 refactor(grpc): move bridge out of orchestrator into grpc module
grpc_bridge.rs → grpc/bridge.rs. The bridge maps OrchestratorEvents
to protobuf ServerMessages — it imports from orchestrator (downstream)
and grpc protos (sibling). The orchestrator never imports from grpc.
2026-03-23 19:22:22 +00:00
be97b7df78 refactor(orchestrator): unified engine + clean public API
- Single run_tool_loop() replaces chat/code-specific variants
- generate() for ConversationRegistry path
- generate_from_response() for caller-managed conversations
- Engine uses ToolContext via execute_with_context(), no ResponseContext
- No imports from grpc, sync, matrix, context, or agent_ux modules
2026-03-23 19:21:36 +00:00
bde770956c refactor(orchestrator): transport-agnostic event types
Replace transport-coupled types with clean abstractions:
- GenerateRequest: single entry point, no room_id/session_id
- Metadata: opaque key-value bag for transport routing data
- ToolContext: replaces ResponseContext in tool execution
- TokenUsage: clean token count struct
- Simplified OrchestratorEvent: remove AgentProgress*, MemoryExtraction*

Removed: ResponseMode, ChatRequest, CodeRequest.
2026-03-23 19:21:22 +00:00
9e5f7e61be feat(orchestrator): Phase 2 engine + tokenizer + tool dispatch
Orchestrator engine:
- engine.rs: unified Mistral Conversations API tool loop that emits
  OrchestratorEvent instead of calling Matrix/gRPC directly
- tool_dispatch.rs: ToolSide routing (client vs server tools)
- Memory loading stubbed (migrates in Phase 4)

Server-side tokenizer:
- tokenizer.rs: HuggingFace tokenizers-rs with Mistral's BPE tokenizer
- count_tokens() for accurate usage metrics
- Loads from local tokenizer.json or falls back to bundled vocab
- Config: mistral.tokenizer_path (optional)

No behavior change — engine is wired but not yet called from
sync.rs or session.rs (Phase 2 continuation).
2026-03-23 17:40:25 +00:00
ec4fde7b97 feat(orchestrator): Phase 1 — event types + broadcast channel foundation
Introduces the orchestrator module with:
- OrchestratorEvent enum: 11 event variants covering lifecycle, tools,
  progress, and side effects
- RequestId (UUID per generation), ResponseMode (Chat/Code), ToolSide
- ChatRequest/CodeRequest structs for transport-agnostic request input
- Orchestrator struct with tokio::broadcast channel (capacity 256)
- subscribe() for transport bridges, emit() for the engine
- Client-side tool dispatch: pending_client_tools map with oneshot channels
- submit_tool_result() to unblock engine from gRPC client responses

Additive only — no behavior change. Existing responder + gRPC session
paths are untouched. Phase 2 will migrate the Conversations API path.
2026-03-23 17:30:36 +00:00
b8b76687a5 feat(grpc): dev mode, agent prefix, system prompt, error UX
- gRPC dev_mode config: disables JWT auth, uses fixed dev identity
- Agent prefix (agents.agent_prefix): dev agents use "dev-sol-orchestrator"
  to avoid colliding with production on shared Mistral accounts
- Coding sessions use instructions (system prompt + coding addendum)
  with mistral-medium-latest for personality adherence
- Conversations API: don't send both model + agent_id (422 fix)
- GrpcState carries system_prompt + orchestrator_agent_id
- Session.end() keeps session active for reuse (not "ended")
- User messages posted as m.notice, assistant as m.text (role detection)
- History loaded from Matrix room on session resume
- Docker Compose local dev stack: OpenSearch 3 + Tuwunel + SearXNG
- Dev config: localhost URLs, dev_mode, opensearch-init.sh for ML setup
2026-03-23 17:07:50 +00:00
71392cef9c feat(code): wire gRPC server into Sol startup
spawns gRPC server alongside Matrix sync loop when [grpc] config
is present. shares ToolRegistry, Store, MistralClient, and Matrix
client with the gRPC CodeSession handler.
2026-03-23 13:01:36 +00:00
abfad337c5 feat(code): CodeSession + agent loop + Matrix room bridge
phase 2 server core:
- CodeSession: create/resume sessions, Matrix room per project,
  Mistral conversation lifecycle, tool dispatch loop
- agent loop: user input → Mistral → tool calls → route (client
  via gRPC / server via ToolRegistry) → collect results → respond
- Matrix bridge: all messages posted to project room, accessible
  from any Matrix client
- code_sessions SQLite table (Postgres-compatible schema)
- coding mode context injection (project path, git info, prompt.md)
2026-03-23 11:46:22 +00:00
35b6246fa7 feat(code): gRPC server with JWT auth + tool routing
tonic 0.14 gRPC server for sunbeam code sessions:
- bidirectional streaming Session RPC
- JWT interceptor validates tokens against Hydra JWKS
- tool router classifies calls as client-side (file_read, bash,
  grep, etc.) or server-side (gitea, identity, search, etc.)
- service stub with session lifecycle (start, chat, tool results, end)
- coding_model config (default: devstral-small-2506)
- grpc config section (listen_addr, jwks_url)
- 182 tests (5 new: JWT claims, tool routing)

phase 2 TODOs: Matrix room bridge, Mistral agent loop, streaming
2026-03-23 11:35:37 +00:00
2a1d7a003d auto-recover corrupted conversations on API error
when append_conversation fails (422, 404, etc.), the stale mapping
is deleted and a fresh conversation is created automatically.
prevents Sol from being permanently stuck after a hung research
session or Mistral API error.
v1.1.0
2026-03-23 09:53:29 +00:00
1ba4e016ba add self-hosted web search via SearXNG
new search_web tool calls SearXNG (cluster-internal, free, no tracking)
instead of Mistral's built-in web_search ($0.03/query + rate limits).

returns structured results from DuckDuckGo, Wikipedia, StackOverflow,
GitHub, arXiv, and Brave. no API keys, no cost, no rate limits.

removed Mistral AgentTool::web_search() from orchestrator — replaced
by the custom tool which goes through Sol's normal tool dispatch.
2026-03-23 09:52:56 +00:00
567d4c1171 fix research agent hang: per-agent timeout + startup cleanup
research agents now have a 2-minute timeout via tokio::time::timeout.
a hung Mistral API call can no longer block Sol's entire sync loop.
timed-out agents return partial results instead of hanging forever.

on startup, Sol detects research sessions with status='running' from
previous crashes and marks them as failed. 6 new tests covering the
full research session lifecycle: create, append findings, complete,
fail, hung cleanup, and partial findings survival.
2026-03-23 09:03:03 +00:00
447bead0b7 wire up identity agent, research tool, silence state
main.rs: create KratosClient, pass mistral+store to ToolRegistry,
build active_agents list for dynamic delegation.

conversations.rs: context_hint for new conversations, reset_all.
sdk/mod.rs: added kratos module.
2026-03-23 01:43:51 +00:00
de33ddfe33 multi-agent research: parallel LLM-powered investigation
new research tool spawns 3-25 micro-agents (ministral-3b) in
parallel via futures::join_all. each agent gets its own Mistral
conversation with full tool access.

recursive spawning up to depth 4 — agents can spawn sub-agents.
research sessions persisted in SQLite (survive reboots).
thread UX: 🔍 reaction, per-agent progress posts,  when done.

cost: ~$0.03 per research task (20 micro-agents on ministral-3b).
2026-03-23 01:42:40 +00:00
7dbc8a3121 room overlap access control for cross-room search
search_archive, get_room_context, and sol.search() (in run_script)
enforce a configurable member overlap threshold. results from a
room are only visible if >=25% of that room's members are also in
the requesting room.

system-level filter applied at the opensearch query layer — sol
never sees results from excluded rooms.
2026-03-23 01:42:20 +00:00
7324c10d25 proper Matrix threading + concise tool call formatting
agent_ux: uses Relation::Thread (not Reply) for tool call details.
format_tool_call extracts key params instead of dumping raw JSON.
format_tool_result truncated to 200 chars.

matrix_utils: added make_thread_reply() for threaded responses.
sync.rs routes ThreadReply engagement to threaded messages.
2026-03-23 01:42:08 +00:00
3b62d86c45 evaluator redesign: response types, silence, structural suppression
new engagement types: Respond (inline), ThreadReply (threaded),
React, Ignore. LLM returns response_type to decide HOW to engage.

silence mechanic: "shut up"/"be quiet" sets a 30min per-room timer.
only direct @mention breaks through.

structural suppression (A+B):
- reply to non-Sol human → capped at React
- 3+ human messages since Sol → forced passive mode

threads have a lower relevance threshold (70% of spontaneous).
time context injected into evaluator prompt.
2026-03-23 01:41:57 +00:00
1058afb635 add TimeContext: 25 pre-computed time values for the model
midnight-based day boundaries (today, yesterday, 2 days ago),
week/month boundaries, rolling offsets (1h to 30d). injected
into system prompt via {time_block} and per-message via compact
time line. models no longer need to compute epoch timestamps.
2026-03-23 01:41:44 +00:00
84278fc1f5 add identity agent: 7 kratos admin API tools
list_users, get_user, create_user, recover_user, disable_user,
enable_user, list_sessions. all via kratos admin API (cluster-
internal, no auth needed). email-to-UUID resolution with fallback
search. delete_user and set_password excluded (CLI-only).
2026-03-23 01:41:25 +00:00
8e7c572381 expand gitea tools: 17 new operations (24 total)
repos: create, edit, fork, list org repos
issues: edit, list comments, create comment
PRs: get, create, merge
branches: list, create, delete
orgs: list user orgs, get org
notifications: list

added write:repository and read:notification PAT scopes.
new response types: Comment, Branch, Organization, Notification.
authed_patch and authed_delete helpers with 401 retry.
URL-encoded query params throughout.
2026-03-23 01:41:08 +00:00
822a597a87 sol 1.0.0 — relicense to AGPL-3.0, dual-license model
relicensed from MIT to AGPL-3.0-or-later. commercial license
available for organizations that need private modifications
(does not permit redistribution).

sol 1.0.0 ships with:
- multi-agent architecture with mistral conversations API
- user impersonation via vault-backed PAT provisioning
- gitea integration (first domain agent: devtools)
- per-user memory system with automatic extraction
- full-context evaluator with system prompt awareness
- agent recreation on prompt changes with conversation reset
- web search, sandboxed deno runtime, archive search
v1.0.0
2026-03-22 15:24:02 +00:00