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