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