Skip to content

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.

delete(service: str, key: str) -> bool async

Delete a secret; return True if it existed.

get(service: str, key: str) -> str | None async

Retrieve a secret; return None if not found.

set(service: str, key: str, value: str) -> None async

Store a secret.

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

Bases: Protocol

Text-to-speech engine.

is_speaking() -> bool

Return whether TTS audio is currently playing.

synthesize(*, text: str, voice: str | None = None, speed: float = 1.0) -> bytes async

Return audio bytes (WAV or raw PCM).

VadBackend

Bases: Protocol

Voice activity detector.

process_chunk(*, audio_data: bytes) -> bool

Return True if speech is detected in the chunk.

reset() -> None

Reset internal VAD state.

VisionBackend

Bases: Protocol

Screenshot capture and image captioning.

caption_image(*, image_data: bytes, prompt: str | None = None) -> str async

Return a text caption describing the image.

capture_screenshot() -> bytes async

Capture the screen; return image bytes.

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.