Skip to main content

harn_vm/
lib.rs

1#![allow(clippy::result_large_err, clippy::cloned_ref_to_slice_refs)]
2
3pub mod a2a;
4pub mod agent_events;
5pub mod agent_sessions;
6pub mod atomic_io;
7pub mod bridge;
8mod builtin_id;
9pub mod checkpoint;
10mod chunk;
11mod compiler;
12pub mod connectors;
13pub mod egress;
14pub mod event_log;
15pub mod events;
16pub mod flow;
17mod http;
18pub mod jsonrpc;
19pub mod llm;
20pub mod llm_config;
21pub mod mcp;
22pub mod mcp_card;
23pub mod mcp_protocol;
24pub mod mcp_registry;
25pub mod mcp_server;
26pub mod metadata;
27pub mod observability;
28pub mod orchestration;
29pub mod personas;
30pub mod process_sandbox;
31pub mod provenance;
32pub mod record_filter;
33pub mod runtime_context;
34pub mod runtime_paths;
35pub mod schema;
36pub mod secrets;
37pub(crate) mod shared_state;
38pub mod shells;
39pub mod skills;
40pub mod stdlib;
41pub mod stdlib_modules;
42pub mod store;
43pub(crate) mod synchronization;
44pub mod tenant;
45pub mod tool_annotations;
46pub mod tool_surface;
47pub mod tracing;
48pub mod triggers;
49pub mod trust_graph;
50pub mod value;
51pub mod visible_text;
52mod vm;
53pub mod waitpoints;
54pub mod workspace_path;
55
56pub use builtin_id::BuiltinId;
57pub use checkpoint::register_checkpoint_builtins;
58pub use chunk::*;
59pub use compiler::*;
60pub use connectors::{
61    active_connector_client, active_metrics_registry, clear_active_connector_clients,
62    clear_active_metrics_registry, connector_export_denied_builtin_reason,
63    connector_export_effect_class,
64    cron::{CatchupMode, CronConnector},
65    default_connector_export_policy,
66    harn_module::{
67        load_contract as load_harn_connector_contract, HarnConnector, HarnConnectorContract,
68    },
69    hmac::verify_hmac_signed,
70    install_active_connector_clients, install_active_metrics_registry,
71    is_rust_provider_connector_compat_provider, load_pending_webhook_handshakes,
72    postprocess_normalized_event, ActivationHandle, ClientError, Connector, ConnectorClient,
73    ConnectorCtx, ConnectorError, ConnectorExportEffectClass, ConnectorHttpResponse,
74    ConnectorMetricsSnapshot, ConnectorNormalizeResult, ConnectorRegistry, GenericWebhookConnector,
75    GitHubConnector, HarnConnectorEffectPolicies, LinearConnector, MetricsRegistry,
76    NotionConnector, PersistedNotionWebhookHandshake, PostNormalizeOutcome, ProviderPayloadSchema,
77    RateLimitConfig, RateLimiterFactory, RawInbound, SlackConnector, StreamConnector,
78    TriggerBinding, TriggerKind, TriggerRegistry, WebhookSignatureVariant,
79    RUST_PROVIDER_CONNECTOR_COMPAT_PROVIDERS,
80};
81pub use http::{register_http_builtins, reset_http_state};
82pub use llm::register_llm_builtins;
83pub use llm::trigger_predicate::TriggerPredicateBudget;
84pub use llm::{
85    current_agent_session_id, drain_global_pending_feedback, push_pending_feedback_global,
86    register_session_end_hook,
87};
88pub use mcp::{
89    connect_mcp_server, connect_mcp_server_from_json, connect_mcp_server_from_spec,
90    register_mcp_builtins,
91};
92pub use mcp_card::{fetch_server_card, load_server_card_from_path, CardError};
93pub use mcp_registry::{
94    active_handle as mcp_active_handle, ensure_active as mcp_ensure_active,
95    get_registration as mcp_get_registration, install_active as mcp_install_active,
96    is_registered as mcp_is_registered, register_servers as mcp_register_servers,
97    release as mcp_release, reset as mcp_reset_registry, snapshot_status as mcp_snapshot_status,
98    sweep_expired as mcp_sweep_expired, RegisteredMcpServer, RegistryStatus,
99};
100pub use mcp_server::{
101    take_mcp_serve_prompts, take_mcp_serve_registry, take_mcp_serve_resource_templates,
102    take_mcp_serve_resources, tool_registry_to_mcp_tools, McpServer,
103};
104pub use metadata::{register_metadata_builtins, register_scan_builtins};
105pub use personas::{
106    disable_persona, fire_schedule as fire_persona_schedule, fire_trigger as fire_persona_trigger,
107    format_ms as format_persona_ms, now_ms as persona_now_ms, parse_rfc3339_ms as parse_persona_ms,
108    pause_persona, persona_status, record_persona_spend, register_persona_value_sink,
109    resume_persona, PersonaBudgetPolicy, PersonaBudgetStatus, PersonaLease, PersonaLifecycleState,
110    PersonaRunCost, PersonaRunReceipt, PersonaRuntimeBinding, PersonaStatus,
111    PersonaTriggerEnvelope, PersonaValueEvent, PersonaValueEventKind, PersonaValueSink,
112    PersonaValueSinkRegistration, PERSONA_RUNTIME_TOPIC,
113};
114pub use provenance::{
115    build_signed_receipt, load_or_generate_agent_signing_key, verify_receipt, ProvenanceReceipt,
116    ReceiptBuildOptions, ReceiptVerificationReport,
117};
118pub use record_filter::{normalize_record_filter_expression, CompiledRecordFilter};
119pub use schema::json_to_vm_value;
120pub use stdlib::hitl::{
121    append_hitl_response, ApprovalRequest, HitlHostResponse, HITL_APPROVALS_TOPIC,
122    HITL_DUAL_CONTROL_TOPIC, HITL_ESCALATIONS_TOPIC, HITL_QUESTIONS_TOPIC,
123};
124pub use stdlib::host::{clear_host_call_bridge, set_host_call_bridge, HostCallBridge};
125pub use stdlib::io::take_stderr_buffer;
126pub use stdlib::long_running::cancel_handle as cancel_long_running_handle;
127pub use stdlib::secret_scan::{
128    append_secret_scan_audit, audit_secret_scan_active, scan_content as secret_scan_content,
129    SecretFinding, SECRET_SCAN_AUDIT_TOPIC,
130};
131pub use stdlib::template::{
132    lookup_prompt_consumers, lookup_prompt_span, prompt_render_indices, record_prompt_render_index,
133    PromptSourceSpan, PromptSpanKind,
134};
135pub use stdlib::waitpoint::{
136    process_waitpoint_resume_event, service_waitpoints_once, WAITPOINT_RESUME_TOPIC,
137};
138pub use stdlib::workflow_messages::{
139    workflow_pause_for_base, workflow_publish_query_for_base, workflow_query_for_base,
140    workflow_respond_update_for_base, workflow_resume_for_base, workflow_signal_for_base,
141    workflow_update_for_base, WorkflowMailboxState,
142};
143pub use stdlib::{
144    register_agent_stdlib, register_core_stdlib, register_io_stdlib, register_vm_stdlib,
145};
146pub use store::register_store_builtins;
147pub use tenant::{
148    tenant_event_topic_prefix, tenant_secret_namespace, tenant_topic, validate_tenant_id, ApiKeyId,
149    TenantApiKeyRecord, TenantBudget, TenantEventLog, TenantRecord, TenantRegistrySnapshot,
150    TenantResolutionError, TenantScope, TenantSecretProvider, TenantStatus, TenantStore,
151    TENANT_EVENT_TOPIC_PREFIX, TENANT_REGISTRY_DIR, TENANT_REGISTRY_FILE,
152    TENANT_SECRET_NAMESPACE_PREFIX,
153};
154pub use triggers::{
155    append_dispatch_cancel_request, begin_in_flight, binding_autonomy_budget_would_exceed,
156    binding_budget_would_exceed, binding_version_as_of, classify_trigger_dlq_error,
157    clear_dispatcher_state, clear_orchestrator_budget, clear_trigger_registry, drain,
158    dynamic_deregister, dynamic_register, expected_predicate_cost_usd_micros, finish_in_flight,
159    install_manifest_triggers, install_orchestrator_budget, micros_to_usd,
160    note_autonomous_decision, note_orchestrator_budget_cost, orchestrator_budget_would_exceed,
161    parse_flow_control_duration, pin_trigger_binding, provider_metadata,
162    record_predicate_cost_sample, redact_headers, register_provider_schema,
163    registered_provider_metadata, registered_provider_schema_names, reset_binding_budget_windows,
164    reset_provider_catalog, reset_provider_catalog_with, resolve_live_or_as_of,
165    resolve_live_trigger_binding, resolve_trigger_binding_as_of, run_trigger_harness_fixture,
166    scheduler_in_flight_by_key, scheduler_ready_stats_by_key, snapshot_dispatcher_stats,
167    snapshot_orchestrator_budget, snapshot_trigger_bindings, unpin_trigger_binding, usd_to_micros,
168    worker_claims_topic_name, worker_job_topic_name, worker_response_topic_name, ClaimedWorkerJob,
169    DispatchCancelRequest, DispatchError, DispatchOutcome, DispatchStatus, Dispatcher,
170    DispatcherDrainReport, DispatcherStatsSnapshot, FairnessKey, HeaderRedactionPolicy, InboxIndex,
171    NotionPolledChangeEvent, OrchestratorBudgetConfig, OrchestratorBudgetSnapshot, ProviderCatalog,
172    ProviderCatalogError, ProviderId, ProviderMetadata, ProviderOutboundMethod, ProviderPayload,
173    ProviderRuntimeMetadata, ProviderSchema, ProviderSecretRequirement, ReadyKeyStats,
174    RecordedTriggerBinding, RetryPolicy, SchedulableJob, SchedulerKeyStat, SchedulerPolicy,
175    SchedulerSnapshot, SchedulerState, SchedulerStrategy, SignatureStatus,
176    SignatureVerificationMetadata, StreamEventPayload, TenantId, TraceId, TriggerBatchConfig,
177    TriggerBindingSnapshot, TriggerBindingSource, TriggerBindingSpec,
178    TriggerBudgetExhaustionStrategy, TriggerConcurrencyConfig, TriggerDebounceConfig,
179    TriggerDispatchOutcome, TriggerEvent, TriggerEventId, TriggerExpressionSpec,
180    TriggerFlowControlConfig, TriggerHandlerSpec, TriggerHarnessResult, TriggerId,
181    TriggerMetricsSnapshot, TriggerPredicateSpec, TriggerPriorityOrderConfig,
182    TriggerRateLimitConfig, TriggerRegistryError, TriggerRetryConfig, TriggerSingletonConfig,
183    TriggerState, TriggerThrottleConfig, WorkerQueue, WorkerQueueClaimHandle,
184    WorkerQueueEnqueueReceipt, WorkerQueueInspectSnapshot, WorkerQueueJob, WorkerQueueJobState,
185    WorkerQueuePriority, WorkerQueueResponseRecord, WorkerQueueState, WorkerQueueSummary,
186    DEFAULT_INBOX_RETENTION_DAYS, DEFAULT_STARVATION_AGE_MS, TRIGGERS_LIFECYCLE_TOPIC,
187    TRIGGER_ATTEMPTS_TOPIC, TRIGGER_CANCEL_REQUESTS_TOPIC, TRIGGER_DLQ_TOPIC,
188    TRIGGER_INBOX_CLAIMS_TOPIC, TRIGGER_INBOX_ENVELOPES_TOPIC, TRIGGER_INBOX_LEGACY_TOPIC,
189    TRIGGER_OPERATION_AUDIT_TOPIC, TRIGGER_OUTBOX_TOPIC, TRIGGER_TEST_FIXTURES,
190    WORKER_QUEUE_CATALOG_TOPIC,
191};
192pub use trust_graph::{
193    append_active_trust_record, append_trust_record, group_trust_records_by_trace,
194    policy_for_agent, policy_for_autonomy_tier, query_trust_records, resolve_agent_autonomy_tier,
195    summarize_trust_records, topic_for_agent, trust_score_for, verify_trust_chain, AutonomyTier,
196    TrustAgentSummary, TrustChainReport, TrustOutcome, TrustQueryFilters, TrustRecord, TrustScore,
197    TrustTraceGroup, OPENTRUSTGRAPH_SCHEMA_V0, TRUST_GRAPH_GLOBAL_TOPIC,
198    TRUST_GRAPH_LEGACY_GLOBAL_TOPIC, TRUST_GRAPH_LEGACY_TOPIC_PREFIX, TRUST_GRAPH_TOPIC_PREFIX,
199};
200pub use value::*;
201pub use vm::*;
202
203/// Lex, parse, type-check, and compile source to bytecode in one call.
204/// Bails on the first type error. For callers that need diagnostics
205/// rather than early exit, use `harn_parser::check_source` directly
206/// and then call `Compiler::new().compile(&program)`.
207pub fn compile_source(source: &str) -> Result<Chunk, String> {
208    let program = harn_parser::check_source_strict(source).map_err(|e| e.to_string())?;
209    Compiler::new().compile(&program).map_err(|e| e.to_string())
210}
211
212pub fn json_schema_for_type_expr(type_expr: &harn_parser::TypeExpr) -> Option<serde_json::Value> {
213    let schema = compiler::Compiler::type_expr_to_schema_value(type_expr)?;
214    let json_schema = schema::schema_to_json_schema_value(&schema).ok()?;
215    Some(llm::vm_value_to_json(&json_schema))
216}
217
218pub fn json_schema_for_typed_params(params: &[harn_parser::TypedParam]) -> serde_json::Value {
219    let mut properties = serde_json::Map::new();
220    let mut required = Vec::new();
221
222    for param in params {
223        let param_schema = param
224            .type_expr
225            .as_ref()
226            .and_then(json_schema_for_type_expr)
227            .unwrap_or_else(|| serde_json::json!({}));
228        if param.default_value.is_none() {
229            required.push(serde_json::Value::String(param.name.clone()));
230        }
231        properties.insert(param.name.clone(), param_schema);
232    }
233
234    let mut schema = serde_json::Map::new();
235    schema.insert(
236        "type".to_string(),
237        serde_json::Value::String("object".to_string()),
238    );
239    schema.insert(
240        "properties".to_string(),
241        serde_json::Value::Object(properties),
242    );
243    if !required.is_empty() {
244        schema.insert("required".to_string(), serde_json::Value::Array(required));
245    }
246    serde_json::Value::Object(schema)
247}
248
249/// Reset all thread-local state that can leak between test runs.
250pub fn reset_thread_local_state() {
251    llm::reset_llm_state();
252    llm_config::clear_user_overrides();
253    http::reset_http_state();
254    event_log::reset_active_event_log();
255    stdlib::reset_stdlib_state();
256    connectors::clear_active_connector_clients();
257    orchestration::clear_runtime_hooks();
258    triggers::clear_dispatcher_state();
259    triggers::clear_trigger_registry();
260    events::reset_event_sinks();
261    agent_events::reset_all_sinks();
262    agent_sessions::reset_session_store();
263    mcp_registry::reset();
264}