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