core.infrastructure¶
Infrastructure modules: event publishing, typed event schema, dependency injection protocols, and service registry.
Event Schema¶
core.infrastructure.event_schema
¶
Typed event schema for the Vector Companion runtime.
All runtime events -- audio state, agent tokens, tool calls, mode changes, memory operations, background tasks, errors, audit entries, and autonomy decisions -- flow through this canonical schema.
The Event dataclass is frozen (immutable after creation) to prevent
silent state mutation as events propagate through subscribers.
EventType
¶
Bases: Enum
Canonical set of runtime event types.
Grouped by domain for readability. New types should be added here rather than encoded in free-form strings so that subscribers can exhaustively match on the enum.
AGENT_CHANGED = auto()
class-attribute
instance-attribute
¶
An agent was activated/deactivated or agent state changed.
AGENT_RESPONSE_CANCELLED = auto()
class-attribute
instance-attribute
¶
Agent generation was cancelled mid-stream.
AGENT_RESPONSE_CHUNK = auto()
class-attribute
instance-attribute
¶
One or more tokens emitted by the agent.
AGENT_RESPONSE_END = auto()
class-attribute
instance-attribute
¶
Agent finished generating the current response.
AGENT_RESPONSE_START = auto()
class-attribute
instance-attribute
¶
Agent began generating a response (first token pending).
AGENT_THINK_CHUNK = auto()
class-attribute
instance-attribute
¶
Agent emitted a thinking/reasoning chunk (not spoken).
APPROVAL_DENIED = auto()
class-attribute
instance-attribute
¶
Human denied approval.
APPROVAL_GRANTED = auto()
class-attribute
instance-attribute
¶
Human granted approval.
APPROVAL_REQUESTED = auto()
class-attribute
instance-attribute
¶
Human approval requested for a risky action.
APPROVAL_REVOKED = auto()
class-attribute
instance-attribute
¶
Persistent approval grant/denial was revoked.
APPROVAL_TIMEOUT = auto()
class-attribute
instance-attribute
¶
Approval request timed out (default: deny).
AUDIO_INTERRUPT = auto()
class-attribute
instance-attribute
¶
User interrupt detected during playback.
AUDIO_LOOPBACK_END = auto()
class-attribute
instance-attribute
¶
Loopback recording stopped.
AUDIO_LOOPBACK_START = auto()
class-attribute
instance-attribute
¶
Loopback (TTS capture) recording started.
AUDIO_PLAYBACK_END = auto()
class-attribute
instance-attribute
¶
TTS audio playback finished or was interrupted.
AUDIO_PLAYBACK_START = auto()
class-attribute
instance-attribute
¶
TTS audio playback began.
AUDIO_RECORDING_END = auto()
class-attribute
instance-attribute
¶
Recording stopped; audio buffer ready for transcription.
AUDIO_RECORDING_START = auto()
class-attribute
instance-attribute
¶
Microphone recording began.
AUDIO_TRANSCRIPT_READY = auto()
class-attribute
instance-attribute
¶
Transcription completed; text available in payload.
AUDIO_VAD_SPEECH_END = auto()
class-attribute
instance-attribute
¶
VAD detected voice activity end.
AUDIO_VAD_SPEECH_START = auto()
class-attribute
instance-attribute
¶
VAD detected voice activity onset.
AUDIT_LOG_ENTRY = auto()
class-attribute
instance-attribute
¶
A structured audit entry was recorded.
AUTONOMY_TIER_CHANGED = auto()
class-attribute
instance-attribute
¶
The autonomy tier was changed (policy engine).
BENCHMARK_COMPLETE = auto()
class-attribute
instance-attribute
¶
A benchmark run finished with results.
BENCHMARK_START = auto()
class-attribute
instance-attribute
¶
A benchmark run began.
BG_TASK_CANCELLED = auto()
class-attribute
instance-attribute
¶
Background task was cancelled.
BG_TASK_COMPLETED = auto()
class-attribute
instance-attribute
¶
Background task finished successfully.
BG_TASK_FAILED = auto()
class-attribute
instance-attribute
¶
Background task failed.
BG_TASK_PROGRESS = auto()
class-attribute
instance-attribute
¶
Background task emitted a progress update.
BG_TASK_SPAWNED = auto()
class-attribute
instance-attribute
¶
A background task was created.
CHAT_CLEARED = auto()
class-attribute
instance-attribute
¶
Chat history was cleared.
COMMAND_RESPONSE = auto()
class-attribute
instance-attribute
¶
Response to a previously issued command.
CONFIG_UPDATED = auto()
class-attribute
instance-attribute
¶
Configuration was updated (models, prompts, batch changes).
CONTEXT_WINDOW_WARNING = auto()
class-attribute
instance-attribute
¶
Context window approaching model limit.
CONVERSATIONS_SYNC = auto()
class-attribute
instance-attribute
¶
Full sidebar state hydration event (folders + conversations).
CONVERSATION_CREATED = auto()
class-attribute
instance-attribute
¶
A new conversation was created.
CONVERSATION_DELETED = auto()
class-attribute
instance-attribute
¶
A conversation was deleted (including embeddings).
CONVERSATION_MOVED = auto()
class-attribute
instance-attribute
¶
A conversation was moved to/from a folder.
CONVERSATION_RENAMED = auto()
class-attribute
instance-attribute
¶
A conversation title was changed.
CONVERSATION_SWITCHED = auto()
class-attribute
instance-attribute
¶
Active conversation was switched.
CONVERSATION_TURN_END = auto()
class-attribute
instance-attribute
¶
A conversation turn completed (agent finished, TTS done).
CONVERSATION_TURN_START = auto()
class-attribute
instance-attribute
¶
A new conversation turn began (user input accepted).
EMBEDDING_UPSERTED = auto()
class-attribute
instance-attribute
¶
Message embeddings were upserted into ChromaDB.
ERROR_OCCURRED = auto()
class-attribute
instance-attribute
¶
General runtime error with envelope.
FOLDER_CREATED = auto()
class-attribute
instance-attribute
¶
A new folder was created.
FOLDER_DELETED = auto()
class-attribute
instance-attribute
¶
A folder was deleted (chats become standalone).
FOLDER_RENAMED = auto()
class-attribute
instance-attribute
¶
A folder was renamed.
HEALTH_CHECK = auto()
class-attribute
instance-attribute
¶
Periodic system health check result.
ISOLATION_DOMAIN_DENIED = auto()
class-attribute
instance-attribute
¶
A domain not in the allowlist was blocked.
ISOLATION_PATH_TRAVERSAL_BLOCKED = auto()
class-attribute
instance-attribute
¶
A path traversal attempt was detected and blocked.
ISOLATION_SANDBOX_ERROR = auto()
class-attribute
instance-attribute
¶
A sandboxed subprocess failed with an error.
ISOLATION_SANDBOX_EXECUTED = auto()
class-attribute
instance-attribute
¶
A tool was executed in a sandboxed subprocess.
ISOLATION_SANDBOX_TIMEOUT = auto()
class-attribute
instance-attribute
¶
A sandboxed subprocess exceeded its execution timeout.
MEMORY_DELETED = auto()
class-attribute
instance-attribute
¶
Memory documents or a collection was deleted.
MEMORY_QUERY = auto()
class-attribute
instance-attribute
¶
A memory retrieval query was issued.
MEMORY_RETRIEVAL_RESULT = auto()
class-attribute
instance-attribute
¶
Memory retrieval results available.
MEMORY_UPSERT = auto()
class-attribute
instance-attribute
¶
Documents were upserted into the memory store.
MODEL_SWITCHED = auto()
class-attribute
instance-attribute
¶
Active model was switched.
MODES_UPDATED = auto()
class-attribute
instance-attribute
¶
Bulk mode flags update (multiple modes at once).
MODE_CHANGED = auto()
class-attribute
instance-attribute
¶
A mode flag was toggled.
ONBOARDING_COMPLETED = auto()
class-attribute
instance-attribute
¶
Onboarding finished; user choices saved.
ONBOARDING_STARTED = auto()
class-attribute
instance-attribute
¶
A new onboarding session was started.
ONBOARDING_STEP_CHANGED = auto()
class-attribute
instance-attribute
¶
The user advanced to the next onboarding step.
ORCHESTRATOR_ERROR = auto()
class-attribute
instance-attribute
¶
The orchestrator encountered an error during a turn.
ORCHESTRATOR_RESPONSE_END = auto()
class-attribute
instance-attribute
¶
The orchestrator's primary agent finished generating.
ORCHESTRATOR_RESPONSE_START = auto()
class-attribute
instance-attribute
¶
The orchestrator's primary agent began generating a response.
ORCHESTRATOR_START = auto()
class-attribute
instance-attribute
¶
The orchestrator began processing a conversation turn.
ORCHESTRATOR_WORKER_RESULT = auto()
class-attribute
instance-attribute
¶
A helper worker completed (result available to orchestrator).
ORCHESTRATOR_WORKER_SPAWNED = auto()
class-attribute
instance-attribute
¶
The orchestrator spawned a helper worker.
PARAM_CHANGED = auto()
class-attribute
instance-attribute
¶
A sampling/runtime parameter was changed.
PROVIDER_HEALTH_CHECK = auto()
class-attribute
instance-attribute
¶
Model provider health check result.
RUNTIME_HEALTH_UPDATED = auto()
class-attribute
instance-attribute
¶
DegradedModeManager published a system readiness update.
SCREENSHOT_CAPTION_READY = auto()
class-attribute
instance-attribute
¶
Screenshot captioning completed.
SCREENSHOT_TAKEN = auto()
class-attribute
instance-attribute
¶
Screenshot was captured.
SECRETS_ACCESS = auto()
class-attribute
instance-attribute
¶
A secret was retrieved (audit: username, backend, never value).
SECRETS_DELETE = auto()
class-attribute
instance-attribute
¶
A secret was deleted (audit: username, backend).
SECRETS_STORE = auto()
class-attribute
instance-attribute
¶
A secret was stored (audit: username, backend).
SESSION_RESTORED = auto()
class-attribute
instance-attribute
¶
Conversation history restored from persistent storage.
SIDE_EFFECT_FILE_DELETE = auto()
class-attribute
instance-attribute
¶
A direct file deletion outside ToolHost governance.
SIDE_EFFECT_FILE_WRITE = auto()
class-attribute
instance-attribute
¶
A direct file write outside ToolHost governance.
SIDE_EFFECT_SCREENSHOT = auto()
class-attribute
instance-attribute
¶
A direct screenshot capture outside ToolHost governance.
SIDE_EFFECT_SUBPROCESS = auto()
class-attribute
instance-attribute
¶
A direct subprocess spawn outside ToolHost governance.
STREAM_BACKPRESSURE = auto()
class-attribute
instance-attribute
¶
Bounded audio queue is full; backpressure active.
STREAM_COMPLETE = auto()
class-attribute
instance-attribute
¶
Streaming coordination run completed (all sentences processed).
STREAM_INTERRUPTED = auto()
class-attribute
instance-attribute
¶
Streaming was interrupted (user speech, error, cancellation).
STREAM_SENTENCE_READY = auto()
class-attribute
instance-attribute
¶
A complete sentence is ready for TTS synthesis.
STREAM_TOKEN_START = auto()
class-attribute
instance-attribute
¶
Agent began streaming tokens for the current turn.
STREAM_TTS_FALLBACK = auto()
class-attribute
instance-attribute
¶
TTS synthesis timed out; sentence dropped as fallback.
STREAM_TTS_PLAYBACK_COMPLETE = auto()
class-attribute
instance-attribute
¶
Audio playback finished for a segment.
STREAM_TTS_PLAYBACK_START = auto()
class-attribute
instance-attribute
¶
Audio playback began for a segment.
STREAM_TTS_SYNTHESIS_COMPLETE = auto()
class-attribute
instance-attribute
¶
TTS synthesis finished; audio segment ready.
STREAM_TTS_SYNTHESIS_START = auto()
class-attribute
instance-attribute
¶
TTS synthesis began for a sentence.
SYSTEM_COMMAND = auto()
class-attribute
instance-attribute
¶
A typed command was received from a UI client or test harness.
SYSTEM_ERROR = auto()
class-attribute
instance-attribute
¶
Fatal or unexpected runtime error.
SYSTEM_START = auto()
class-attribute
instance-attribute
¶
Published once the runtime has initialized all services.
SYSTEM_STOP = auto()
class-attribute
instance-attribute
¶
Published during graceful shutdown.
TELEMETRY_SAMPLE_RECORD = auto()
class-attribute
instance-attribute
¶
A metric sample was recorded.
TELEMETRY_SNAPSHOT = auto()
class-attribute
instance-attribute
¶
A system resource snapshot was captured.
TOOL_CALL_APPROVAL_NEEDED = auto()
class-attribute
instance-attribute
¶
Tool call requires human-in-the-loop approval before execution.
TOOL_CALL_DENIED = auto()
class-attribute
instance-attribute
¶
Tool call was denied by policy or user.
TOOL_CALL_ERROR = auto()
class-attribute
instance-attribute
¶
Tool execution failed.
TOOL_CALL_REQUEST = auto()
class-attribute
instance-attribute
¶
Agent requested a tool call.
TOOL_CALL_RESULT = auto()
class-attribute
instance-attribute
¶
Tool execution completed successfully.
TOOL_CALL_TIMEOUT = auto()
class-attribute
instance-attribute
¶
Tool execution exceeded its timeout budget.
UI_AGENT_MESSAGE_CHUNK = auto()
class-attribute
instance-attribute
¶
Streaming text chunk for the current agent message.
UI_AGENT_MESSAGE_END = auto()
class-attribute
instance-attribute
¶
Agent message rendering complete.
UI_AGENT_MESSAGE_START = auto()
class-attribute
instance-attribute
¶
UI should begin rendering an agent message block.
UI_ERROR_BANNER = auto()
class-attribute
instance-attribute
¶
UI should display an error banner.
UI_STATUS_UPDATE = auto()
class-attribute
instance-attribute
¶
General UI status indicator update (mic, memory, tools, etc).
UI_TOOL_CALL_BADGE = auto()
class-attribute
instance-attribute
¶
UI should display a tool-call badge.
UI_USER_MESSAGE = auto()
class-attribute
instance-attribute
¶
User sent a message (voice or text).
USER_SEGMENT_COMPLETE = auto()
class-attribute
instance-attribute
¶
A VAD-detected user speech segment was transcribed (mid-recording).
WORKER_BUDGET_EXCEEDED = auto()
class-attribute
instance-attribute
¶
A helper worker exceeded its token budget.
WORKER_CANCELLED = auto()
class-attribute
instance-attribute
¶
A helper worker was cancelled.
WORKER_COMPLETED = auto()
class-attribute
instance-attribute
¶
A helper worker completed successfully.
WORKER_FAILED = auto()
class-attribute
instance-attribute
¶
A helper worker failed (error, budget, timeout).
WORKER_PROGRESS = auto()
class-attribute
instance-attribute
¶
A helper worker emitted a progress update.
WORKER_RESULT = auto()
class-attribute
instance-attribute
¶
A helper worker produced a result available for consumption.
WORKER_SPAWNED = auto()
class-attribute
instance-attribute
¶
A helper worker was spawned by the WorkerPool.
WORKER_STARTED = auto()
class-attribute
instance-attribute
¶
A helper worker began execution.
WORKER_TIMED_OUT = auto()
class-attribute
instance-attribute
¶
A helper worker exceeded its timeout budget.
Event
dataclass
¶
Immutable runtime event.
Parameters¶
event_type:
The type of event.
event_id:
Unique hex identifier (12-char UUID prefix).
timestamp:
UTC timestamp of event creation.
source:
Originating component (e.g. "audio_pipeline", "agent.axiom").
payload:
Arbitrary structured data attached to the event.
correlation_id:
Links related events across a conversation turn or operation.
sequence_number:
Per-source monotonic counter (used for ordering / gap detection).
from_dict(data: dict[str, Any]) -> Event
classmethod
¶
Deserialize from a plain dictionary.
replace(**changes: Any) -> Event
¶
Return a new Event with the given fields replaced.
Convenience for producing follow-up events (e.g. a COMMAND_RESPONSE that shares the correlation_id of the original command).
to_dict() -> dict[str, Any]
¶
Serialize to a plain dictionary (JSON-friendly).
EventBus¶
core.infrastructure.event_bus
¶
In-process async event bus for the Vector Companion runtime.
Routes Event instances from publishers to registered subscribers.
Supports both sync and async handlers, per-source sequence numbering,
and a catch-all subscriber for audit / logging sinks.
EventBus
¶
Async event bus with typed subscription.
Handlers are called in registration order. Async handlers (coroutines)
are await-ed; sync handlers are called directly. Handler exceptions
are caught and logged so one misbehaving subscriber cannot silence the
rest of the bus.
Parameters¶
swallow_errors:
If True (default), handler exceptions are logged but not
re-raised. Set to False in tests to fail fast.
all_handler_count() -> int
¶
Return the number of catch-all handlers.
clear() -> None
¶
Remove all handlers and reset sequence counters.
handler_count(event_type: EventType) -> int
¶
Return the number of type-specific handlers for event_type.
publish(event: Event, source: str = '') -> Event
async
¶
Publish event, delivering it to all matching subscribers.
If event has sequence_number == 0, a per-source monotonic
counter is incremented and injected before delivery.
Returns the (possibly enriched) event.
subscribe(event_type: EventType, handler: EventHandler) -> None
¶
Register handler for a specific EventType.
subscribe_all(handler: EventHandler) -> None
¶
Register handler for every event type.
Catch-all handlers are called after type-specific handlers.
unsubscribe(event_type: EventType, handler: EventHandler) -> bool
¶
Remove handler from event_type. Returns True if found.
unsubscribe_all(handler: EventHandler) -> bool
¶
Remove handler from the catch-all list.
Service Protocols¶
core.infrastructure.service_protocols
¶
Protocol-based interfaces for dependency-injected services.
These define the seams between the core runtime and its pluggable back-ends. Real implementations, test fakes, and future adapters all conform to the same Protocol contracts so the orchestrator never needs to know which wire it is talking to.
Use typing.Protocol (structural sub-typing) rather than ABC classes
so implementations do not need to inherit from a common base — duck
typing with static-check support via Pyright/mypy.
ApprovalWorkflowProtocol
¶
Bases: Protocol
Manages the lifecycle of human-in-the-loop approvals.
history_count: int
property
¶
Total decisions recorded.
pending_count: int
property
¶
Number of currently pending requests.
check_persistent(tool_name: str) -> Any | None
async
¶
Check if there is a persistent grant/deny for a tool.
clear_history() -> int
async
¶
Clear all decision history; return count cleared.
create(*, tool_name: str, arguments: dict[str, Any], side_effect_level: str, reason: str, preview: str | None = None, timeout_seconds: float | None = None, correlation_id: str = '', caller: str = '') -> str
async
¶
Create a new approval request; return the request_id.
deny(request_id: str, *, rationale: str = '') -> Any
async
¶
Deny approval for a pending request.
get_history(*, tool_name: str | None = None, limit: int = 50) -> list[Any]
async
¶
Return decision history, most recent first.
get_pending(request_id: str) -> Any | None
async
¶
Return the pending request, or None if resolved/expired.
get_result(request_id: str) -> Any | None
async
¶
Look up the result for a resolved request.
grant(request_id: str, *, rationale: str = '') -> Any
async
¶
Grant approval for a pending request.
list_pending() -> list[Any]
async
¶
Return all non-expired pending requests.
revoke_persistent(tool_name: str) -> bool
async
¶
Remove any persistent grant or denial for a tool.
AudioBackend
¶
Bases: Protocol
Microphone capture and audio playback.
is_playing() -> bool
¶
Return whether audio is currently playing.
is_recording() -> bool
¶
Return whether the microphone is currently recording.
start_playback(*, audio_data: bytes) -> None
async
¶
Begin playing audio data through the default output device.
start_recording(*, device_index: int | None = None) -> None
async
¶
Begin capturing from the microphone.
stop_playback() -> None
async
¶
Interrupt current playback.
stop_recording() -> bytes
async
¶
Stop recording; return raw PCM/WAV bytes.
AuditLog
¶
Bases: Protocol
Structured append-only audit trail.
log(*, event_type: str, source: str, correlation_id: str = '', data: dict[str, Any] | None = None, level: str = 'info') -> None
async
¶
Append an audit entry.
query(*, event_type: str | None = None, source: str | None = None, correlation_id: str | None = None, level: str | None = None, limit: int = 100) -> list[dict[str, Any]]
async
¶
Return matching audit entries (most recent first).
AutonomyPolicy
¶
Bases: Protocol
Tiered autonomy with per-tool permission gates.
tier: int
property
¶
Current autonomy tier (0-3).
max_tool_calls_per_turn() -> int
¶
Maximum recursive tool calls allowed per generation turn.
requires_approval(tool_name: str) -> bool
¶
Check if a tool needs human-in-the-loop approval.
set_tier(tier: int) -> None
¶
Change the autonomy tier.
tier_name() -> str
¶
Return the human-readable tier name (Companion / Assistant / Operator / Automation).
tool_allowed(tool_name: str, side_effect_level: str) -> bool
¶
Check if a tool is allowed at the current tier.
BackgroundTaskQueue
¶
Bases: Protocol
Bounded task queue with status tracking and cancellation.
cancel(task_id: str) -> bool
async
¶
Cancel a running or pending task.
enqueue(*, task_id: str, description: str, coroutine: Any, priority: int = 0, timeout: float | None = None) -> None
async
¶
Add a coroutine to the queue.
list_tasks() -> list[dict[str, Any]]
async
¶
Return all active task status dicts.
result(task_id: str, *, timeout: float | None = None) -> Any
async
¶
Block until the task finishes; return the result.
status(task_id: str) -> dict[str, Any] | None
async
¶
Return task status dict, or None if unknown.
EventBusProtocol
¶
Bases: Protocol
Typed async event bus.
clear() -> None
¶
Remove all handlers.
handler_count(event_type: EventType) -> int
¶
Return handler count for event_type.
publish(event: Event, source: str = '') -> Event
async
¶
Publish event to all matching subscribers.
subscribe(event_type: EventType, handler: Any) -> None
¶
Register handler for a specific event type.
subscribe_all(handler: Any) -> None
¶
Register handler for all event types.
unsubscribe(event_type: EventType, handler: Any) -> bool
¶
Remove handler from event_type.
unsubscribe_all(handler: Any) -> bool
¶
Remove handler from the catch-all list.
LocalStoreProtocol
¶
Bases: Protocol
Canonical SQLite-backed local persistence store.
Covers conversations, messages, settings, memories, attachments, audit events, tool grants, background tasks, folders, and embedding index in a single WAL-mode database. ChromaDB remains the semantic index adapter; embeddings are rebuildable from the canonical store.
add_attachment(*, message_id: str, atype: str, data_path: str = '', data_bytes: bytes | None = None, metadata: dict | None = None) -> Any
async
¶
Add an attachment to a message.
add_message(*, conversation_id: str, role: str, content: str, tool_call_id: str = '', metadata: dict | None = None, tool_name: str = '') -> Any
async
¶
Add a message to a conversation.
conversation_count() -> int
async
¶
Return the total number of conversations.
create_conversation(*, agent: str, mode_flags: dict | None = None, metadata: dict | None = None, title: str = '', folder_id: str | None = None) -> Any
async
¶
Create a new conversation.
create_folder(*, name: str) -> Any
async
¶
Create a new folder.
create_task(*, task_id: str, description: str) -> Any
async
¶
Create a new background task record.
db_path() -> str
¶
Return the database file path.
delete_conversation(conversation_id: str) -> int
async
¶
Delete a conversation and its messages (cascade).
delete_embeddings_for_conversation(conversation_id: str) -> int
async
¶
Delete embedding index entries for a conversation.
delete_folder(folder_id: str) -> int
async
¶
Delete a folder (conversations become standalone).
delete_memory(doc_id: str) -> bool
async
¶
Delete a memory by doc_id.
get_conversation(conversation_id: str) -> Any | None
async
¶
Fetch a conversation by ID.
get_embedding_index(message_id: str) -> Any | None
async
¶
Fetch embedding index entry by message_id.
get_embedding_index_by_conversation(conversation_id: str) -> list[Any]
async
¶
Fetch all embedding index entries for a conversation.
get_folder(folder_id: str) -> Any | None
async
¶
Fetch a folder by ID.
get_messages(conversation_id: str, *, limit: int | None = 100, offset: int = 0) -> list[Any]
async
¶
Get messages for a conversation, newest first.
When limit is None, returns all messages.
get_setting(key: str, default: Any = None) -> Any
async
¶
Get a setting by key.
get_task(task_id: str) -> Any | None
async
¶
Fetch a task by ID.
get_tool_grant(tool_name: str) -> Any | None
async
¶
Fetch the most recent grant/denial for a tool.
grant_tool(*, tool_name: str, decision: str, persistent: bool = False) -> Any
async
¶
Record a tool grant or denial.
has_persistent_deny(tool_name: str) -> bool
async
¶
Check if a tool has a persistent denial.
has_persistent_grant(tool_name: str) -> bool
async
¶
Check if a tool has a persistent grant.
list_all_with_folders() -> dict[str, Any]
async
¶
Return folders and conversations for sidebar hydration.
list_attachments(message_id: str) -> list[Any]
async
¶
List attachments for a message.
list_conversations(*, agent: str | None = None, limit: int | None = 50) -> list[Any]
async
¶
List conversations, optionally filtered by agent.
When limit is None, returns all conversations.
list_folders() -> list[Any]
async
¶
Return all folders ordered by name.
list_memories(*, collection: str, limit: int = 100) -> list[Any]
async
¶
List memories in a collection.
list_settings() -> dict[str, Any]
async
¶
Return all settings as a dict.
list_tasks(*, status: str | None = None, limit: int = 50) -> list[Any]
async
¶
List tasks, optionally filtered by status.
memory_count(*, collection: str | None = None) -> int
async
¶
Count memories, optionally filtered by collection.
message_count(conversation_id: str) -> int
async
¶
Count messages in a conversation.
schema_version() -> int
¶
Return the current schema version.
set_setting(key: str, value: Any) -> None
async
¶
Set a setting (upsert).
update_conversation(conversation_id: str, *, ended_at: str | None = None, metadata: dict | None = None, title: str | None = None, folder_id: str | None = ...) -> bool
async
¶
Update conversation fields.
update_folder(folder_id: str, *, name: str) -> bool
async
¶
Rename a folder.
update_task_status(task_id: str, *, status: str, result: dict | None = None, error: str | None = None) -> bool
async
¶
Update task status and optional fields.
upsert_embedding_index(*, message_id: str, chroma_doc_id: str, collection: str, folder_id: str | None, conversation_id: str) -> Any
async
¶
Record or update an embedding index entry.
upsert_memory(*, collection: str, document: str, embedding_ref: str = '', metadata: dict | None = None, doc_id: str | None = None) -> Any
async
¶
Insert or update a memory record.
MemoryStore
¶
Bases: Protocol
Semantic memory backed by a vector index or relational store.
create_collection(name: str) -> None
async
¶
Create a collection if it does not already exist.
delete(*, collection: str, ids: list[str] | None = None, where: dict[str, Any] | None = None) -> int
async
¶
Delete matching documents; return count removed.
delete_collection(name: str) -> None
async
¶
Drop a collection entirely.
list_collections() -> list[str]
async
¶
Return all collection names.
query(*, collection: str, query_texts: list[str], n_results: int = 5, where: dict[str, Any] | None = None) -> dict[str, Any]
async
¶
Return closest documents.
The return dict should contain at least:
- documents: list[list[str]]
- distances: list[list[float]]
- metadatas: list[list[dict]]
- ids: list[list[str]]
upsert(*, collection: str, documents: list[str], metadatas: list[dict[str, Any]] | None = None, ids: list[str] | None = None) -> list[str]
async
¶
Insert or update documents; return document IDs.
MetricsCollectorProtocol
¶
Bases: Protocol
Local-first performance metrics collector.
Records timing samples, gauges, and provides percentile summaries. All data stays local — no network calls.
export_json(path: Any) -> None
async
¶
Export all samples and gauges to a JSON file.
gauge(name: str, value: float, labels: dict[str, str] | None = None) -> Any
¶
Record or update a gauge value.
get_gauges(name: str | None = None) -> dict[str, Any]
¶
Retrieve current gauge values.
get_samples(name: str | None = None, limit: int = 1000) -> list[Any]
¶
Retrieve samples, optionally filtered by name.
get_summary(window_seconds: float = 60.0) -> dict[str, Any]
¶
Compute per-metric min/p50/p95/max/count over a time window.
record(name: str, value: float, unit: str = 'ms', labels: dict[str, str] | None = None, correlation_id: str = '') -> Any
¶
Record a metric sample (timing, counter, etc.).
reset() -> None
¶
Clear all stored samples and gauges.
ModelBackend
¶
Bases: Protocol
Streaming local or remote LLM inference engine.
cancel() -> None
¶
Signal in-flight generation to stop (if supported).
chat(*, model: str, messages: list[dict[str, str]], system_prompt: list[str] | str | None = None, temperature: float = 1.0, top_p: float = 0.95, top_k: int = 64, num_ctx: int = 8192, tools: list[dict[str, Any]] | None = None, think: bool | str | None = None, seed: int | None = None) -> dict[str, Any]
async
¶
Return the full response (non-streaming) as a dict.
chat_stream(*, model: str, messages: list[dict[str, str]], system_prompt: list[str] | str | None = None, temperature: float = 1.0, top_p: float = 0.95, top_k: int = 64, num_ctx: int = 8192, tools: list[dict[str, Any]] | None = None, think: bool | str | None = None, seed: int | None = None) -> AsyncIterator[str]
async
¶
Yield raw token strings as the model generates a response.
embed(*, model: str, texts: list[str]) -> list[list[float]]
async
¶
Return embeddings for each text.
health_check() -> dict[str, Any]
async
¶
Return a health status dict ({"healthy": True, "status": "ok"}).
list_models() -> list[str]
async
¶
Return available model names.
OrchestratorProtocol
¶
Bases: Protocol
Primary conversation orchestrator with helper-worker delegation.
Wraps a primary agent and a worker pool. On each turn it optionally spawns helper workers (planner, retriever, summarizer), enriches the agent prompt with worker results, and streams the primary agent's response.
is_available: bool
property
¶
Return whether the orchestrator is ready to process turns.
primary_agent_name: str
property
¶
Name of the primary agent.
delegate(worker_type: Any, inputs: dict[str, Any] | None = None) -> Any
async
¶
Spawn a single helper worker and wait for the result.
orchestrate(user_text: str, vector_text: str = '', *, correlation_id: str = '', memory_mode: bool = False, extra_context: str = '') -> Any
async
¶
Run one full orchestration turn.
Spawns helper workers as needed, calls the primary agent with enriched context, and returns the result.
PluginManagerProtocol
¶
Bases: Protocol
Plugin manifest loader with lifecycle management.
Discovers, installs, enables, disables, and unloads plugins
from the plugins/ directory. Each plugin carries a signed,
versioned manifest that declares permissions and dependencies.
Plugins are disabled by default until explicitly enabled.
disable(name: str) -> Any
¶
Disable an enabled plugin.
discover(manifest: Any) -> Any
¶
Register a plugin from a manifest (does not auto-enable).
enable(name: str) -> Any
¶
Enable an installed plugin.
install(name: str, path: str = '') -> Any
¶
Install a plugin by name (from disk or registry).
list_plugins(*, enabled_only: bool = False) -> list[Any]
¶
List installed plugins, optionally filtered by status.
uninstall(name: str) -> bool
¶
Uninstall a plugin entirely.
ProcessIsolationProtocol
¶
Bases: Protocol
Process isolation for risky tool execution.
Validates paths and domains against allowlists, scans arguments for traversal attacks, and optionally executes tools in sandboxed subprocesses with timeout and environment filtering.
execute(*, handler: Any, arguments: dict[str, Any], side_effect: str = 'none', module_name: str | None = None, function_name: str | None = None, timeout: float | None = None) -> Any
async
¶
Execute a tool handler with appropriate isolation.
get_isolation_level(side_effect: str) -> Any
¶
Return the isolation level for a side-effect classification.
should_isolate(side_effect: str) -> bool
¶
Return True if tools with this side-effect need subprocess
isolation.
validate_arguments(arguments: dict[str, Any]) -> list[str]
¶
Scan arguments for path/domain violations.
Returns a list of issues (empty = clean).
SecretStore
¶
Bases: Protocol
Secure credential storage backed by the OS keychain/keyring.
SettingsStore
¶
Bases: Protocol
Key-value or document store for application settings.
delete(key: str) -> bool
async
¶
Remove a setting; return True if it existed.
from_dict(data: dict[str, Any]) -> None
async
¶
Overwrite all settings from a dict.
get(key: str, default: Any = None) -> Any
async
¶
Retrieve a setting value.
keys() -> list[str]
async
¶
Return all setting keys.
set(key: str, value: Any) -> None
async
¶
Persist a setting value.
to_dict() -> dict[str, Any]
async
¶
Dump all settings as a dict.
StreamingCoordinatorProtocol
¶
Bases: Protocol
Coordinates agent response streaming with TTS synthesis and playback.
Manages a bounded audio queue with backpressure, user-interrupt detection, and structured event publication for the entire streaming lifecycle. Supports both batch (list[str]) and streaming (AsyncGenerator) sentence inputs.
is_running: bool
property
¶
Return whether a streaming run is currently active.
queue_depth: int
property
¶
Return the current number of audio segments waiting playback.
coordinate(sentences: list[str] | None = None, *, sentences_generator: Any | None = None, sample_rate: int = 24000, correlation_id: str = '') -> StreamingResult
async
¶
Run the full producer/consumer streaming pipeline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sentences
|
list[str] | None
|
Sentences to synthesize and play. Mutually exclusive with sentences_generator. |
None
|
sentences_generator
|
Any | None
|
Async generator yielding sentences one-at-a-time (enables true streaming). |
None
|
sample_rate
|
int
|
Audio sample rate (default 24000). |
24000
|
correlation_id
|
str
|
Links all events for this turn. |
''
|
Returns:
| Type | Description |
|---|---|
StreamingResult
|
StreamingResult with summary statistics. |
interrupt(reason: Any) -> None
¶
Signal the coordinator to stop (e.g. user speech detected).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reason
|
Any
|
An InterruptReason value. |
required |
ToolHost
¶
Bases: Protocol
Executes tools through a policy-gated, auditable boundary.
approve_tool_call(*, tool_name: str, arguments: dict[str, Any], grant: bool, persistent: bool = False) -> None
async
¶
Record a manual approval or denial decision.
execute(*, tool_name: str, arguments: dict[str, Any], correlation_id: str = '', caller: str = '') -> dict[str, Any]
async
¶
Validate manifest → check policy → HITL if needed → execute.
Returns a dict with result, success, and optional error.
get_tool_manifest(tool_name: str) -> dict[str, Any] | None
async
¶
Return the manifest for a single tool, or None.
list_tools() -> list[dict[str, Any]]
async
¶
Return active tool manifests.
TranscriptionBackend
¶
Bases: Protocol
Speech-to-text engine.
transcribe(*, audio_data: bytes, language: str | None = None) -> str
async
¶
Return the transcription text.
TtsBackend
¶
VadBackend
¶
VisionBackend
¶
WorkerPoolProtocol
¶
Bases: Protocol
Manages bounded concurrent helper workers (non-speaking, internal).
Workers communicate through typed internal events, not free-form chat. Each worker has budget limits, cancellation, trace events, and explicit ownership of inputs/outputs.
history_count: int
property
¶
Number of results in history.
running_count: int
property
¶
Number of currently running workers.
cancel(worker_id: str) -> bool
async
¶
Request cancellation of a running worker.
get_history(*, worker_type: Any | None = None, status: Any | None = None, limit: int | None = None) -> list[Any]
async
¶
Query worker result history (most recent first).
get_result(worker_id: str) -> Any | None
async
¶
Look up a completed worker result by ID.
list_tasks() -> list[dict[str, Any]]
async
¶
Return a summary of all currently running workers.
register_executor(worker_type: Any, executor: Any) -> None
async
¶
Register an async executor function for a WorkerType.
spawn(config: Any, inputs: dict[str, Any], *, correlation_id: str = '', cancel_event: Any | None = None) -> str
async
¶
Spawn a new helper worker; return the worker_id.
wait_for(worker_id: str, *, timeout: float | None = None) -> Any | None
async
¶
Wait for a worker to complete and return the result.
Service Registry¶
core.infrastructure.service_registry
¶
Dependency-injected service container for the Vector Companion runtime.
The ServiceRegistry is a lightweight, protocol-based DI container.
Services are registered at startup (or in test fixtures) and resolved
by their Protocol type rather than concrete classes. This removes
hard-coded construction from main.py and enables fake implementations
in tests.
Usage¶
registry = ServiceRegistry() registry.register(ModelBackend, fake_model) registry.register(MemoryStore, fake_memory) backend = registry.resolve(ModelBackend) # returns fake_model
ServiceRegistry
¶
Lightweight protocol-based dependency injection container.
Services are stored in a dict[type, instance]. Resolution looks
up the exact Protocol class; no subclassing or coercion is
attempted. This keeps the container predictable and fast.
Parameters¶
strict : bool
If True (default), resolve() raises
ServiceNotFoundError for missing services. If False,
None is returned instead.
audio_backend: AudioBackend
property
¶
Resolve the AudioBackend.
audit_log: AuditLog
property
¶
Resolve the AuditLog.
autonomy_policy: AutonomyPolicy
property
¶
Resolve the AutonomyPolicy.
event_bus: EventBusProtocol
property
¶
Resolve the EventBus.
local_store: LocalStoreProtocol
property
¶
Resolve the LocalStoreProtocol.
memory_store: MemoryStore
property
¶
Resolve the MemoryStore.
model_backend: ModelBackend
property
¶
Resolve the ModelBackend.
orchestrator: OrchestratorProtocol
property
¶
Resolve the OrchestratorProtocol.
plugin_manager: PluginManagerProtocol
property
¶
Resolve the PluginManagerProtocol.
secret_store: SecretStore
property
¶
Resolve the SecretStore.
settings_store: SettingsStore
property
¶
Resolve the SettingsStore.
task_queue: BackgroundTaskQueue
property
¶
Resolve the BackgroundTaskQueue.
tool_host: ToolHost
property
¶
Resolve the ToolHost.
transcription_backend: TranscriptionBackend
property
¶
Resolve the TranscriptionBackend.
tts_backend: TtsBackend
property
¶
Resolve the TtsBackend.
vad_backend: VadBackend
property
¶
Resolve the VadBackend.
vision_backend: VisionBackend
property
¶
Resolve the VisionBackend.
clear() -> None
¶
Remove all service bindings.
get_or_default(service_type: type, default: Any = None) -> Any
¶
Return the registered instance or default if absent.
has(service_type: type) -> bool
¶
Return True if service_type has been registered.
register(service_type: type, instance: Any) -> None
¶
Bind instance to service_type.
If an instance was already registered for the same type, it is silently overwritten (useful for test fixtures that swap fakes).
register_if_absent(service_type: type, instance: Any) -> bool
¶
Bind instance only if service_type has no registration yet.
Returns True if the instance was registered, False if it
was skipped because an existing registration was found.
registered_types() -> list[type]
¶
Return all registered service types.
resolve(service_type: type) -> Any
¶
Return the registered instance for service_type.
Raises ServiceNotFoundError if the service is not registered
and strict mode is enabled. Returns None in non-strict mode.
summary() -> str
¶
Return a human-readable registration summary.
unregister(service_type: type) -> None
¶
Remove the binding for service_type.