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;
7pub mod checkpoint;
8mod chunk;
9mod compiler;
10pub mod connectors;
11pub mod event_log;
12pub mod events;
13mod http;
14pub mod jsonrpc;
15pub mod llm;
16pub mod llm_config;
17pub mod mcp;
18pub mod mcp_card;
19pub mod mcp_registry;
20pub mod mcp_server;
21pub mod metadata;
22pub mod observability;
23pub mod orchestration;
24pub mod record_filter;
25pub mod runtime_paths;
26pub mod schema;
27pub mod secrets;
28pub mod skills;
29pub mod stdlib;
30pub mod stdlib_modules;
31pub mod store;
32pub mod tool_annotations;
33pub mod tracing;
34pub mod triggers;
35pub mod trust_graph;
36pub mod value;
37pub mod visible_text;
38mod vm;
39pub mod workspace_path;
40
41pub use checkpoint::register_checkpoint_builtins;
42pub use chunk::*;
43pub use compiler::*;
44pub use connectors::{
45    active_connector_client, clear_active_connector_clients,
46    cron::{CatchupMode, CronConnector},
47    hmac::verify_hmac_signed,
48    install_active_connector_clients, load_pending_webhook_handshakes,
49    postprocess_normalized_event, ActivationHandle, ClientError, Connector, ConnectorClient,
50    ConnectorCtx, ConnectorError, ConnectorMetricsSnapshot, ConnectorRegistry,
51    GenericWebhookConnector, GitHubConnector, LinearConnector, MetricsRegistry, NotionConnector,
52    PersistedNotionWebhookHandshake, PostNormalizeOutcome, ProviderPayloadSchema, RateLimitConfig,
53    RateLimiterFactory, RawInbound, SlackConnector, TriggerBinding, TriggerKind, TriggerRegistry,
54    WebhookSignatureVariant,
55};
56pub use http::{register_http_builtins, reset_http_state};
57pub use llm::register_llm_builtins;
58pub use llm::trigger_predicate::TriggerPredicateBudget;
59pub use mcp::{
60    connect_mcp_server, connect_mcp_server_from_json, connect_mcp_server_from_spec,
61    register_mcp_builtins,
62};
63pub use mcp_card::{fetch_server_card, load_server_card_from_path, CardError};
64pub use mcp_registry::{
65    active_handle as mcp_active_handle, ensure_active as mcp_ensure_active,
66    get_registration as mcp_get_registration, install_active as mcp_install_active,
67    is_registered as mcp_is_registered, register_servers as mcp_register_servers,
68    release as mcp_release, reset as mcp_reset_registry, snapshot_status as mcp_snapshot_status,
69    sweep_expired as mcp_sweep_expired, RegisteredMcpServer, RegistryStatus,
70};
71pub use mcp_server::{
72    take_mcp_serve_prompts, take_mcp_serve_registry, take_mcp_serve_resource_templates,
73    take_mcp_serve_resources, tool_registry_to_mcp_tools, McpServer,
74};
75pub use metadata::{register_metadata_builtins, register_scan_builtins};
76pub use record_filter::{normalize_record_filter_expression, CompiledRecordFilter};
77pub use stdlib::hitl::{
78    append_hitl_response, HitlHostResponse, HITL_APPROVALS_TOPIC, HITL_DUAL_CONTROL_TOPIC,
79    HITL_ESCALATIONS_TOPIC, HITL_QUESTIONS_TOPIC,
80};
81pub use stdlib::host::{clear_host_call_bridge, set_host_call_bridge, HostCallBridge};
82pub use stdlib::secret_scan::{
83    append_secret_scan_audit, audit_secret_scan_active, scan_content as secret_scan_content,
84    SecretFinding, SECRET_SCAN_AUDIT_TOPIC,
85};
86pub use stdlib::template::{
87    lookup_prompt_consumers, lookup_prompt_span, prompt_render_indices, record_prompt_render_index,
88    PromptSourceSpan, PromptSpanKind,
89};
90pub use stdlib::{
91    register_agent_stdlib, register_core_stdlib, register_io_stdlib, register_vm_stdlib,
92};
93pub use store::register_store_builtins;
94pub use triggers::{
95    append_dispatch_cancel_request, begin_in_flight, binding_version_as_of, clear_dispatcher_state,
96    clear_trigger_registry, drain, dynamic_deregister, dynamic_register, finish_in_flight,
97    install_manifest_triggers, parse_flow_control_duration, pin_trigger_binding, provider_metadata,
98    redact_headers, register_provider_schema, registered_provider_metadata,
99    registered_provider_schema_names, reset_provider_catalog, resolve_live_or_as_of,
100    resolve_live_trigger_binding, resolve_trigger_binding_as_of, run_trigger_harness_fixture,
101    snapshot_dispatcher_stats, snapshot_trigger_bindings, unpin_trigger_binding,
102    worker_claims_topic_name, worker_job_topic_name, worker_response_topic_name, ClaimedWorkerJob,
103    DispatchCancelRequest, DispatchError, DispatchOutcome, DispatchStatus, Dispatcher,
104    DispatcherDrainReport, DispatcherStatsSnapshot, HeaderRedactionPolicy, InboxIndex,
105    NotionPolledChangeEvent, ProviderCatalog, ProviderCatalogError, ProviderId, ProviderMetadata,
106    ProviderOutboundMethod, ProviderPayload, ProviderRuntimeMetadata, ProviderSchema,
107    ProviderSecretRequirement, RecordedTriggerBinding, RetryPolicy, SignatureStatus,
108    SignatureVerificationMetadata, TenantId, TraceId, TriggerBatchConfig, TriggerBindingSnapshot,
109    TriggerBindingSource, TriggerBindingSpec, TriggerConcurrencyConfig, TriggerDebounceConfig,
110    TriggerDispatchOutcome, TriggerEvent, TriggerEventId, TriggerExpressionSpec,
111    TriggerFlowControlConfig, TriggerHandlerSpec, TriggerHarnessResult, TriggerId,
112    TriggerMetricsSnapshot, TriggerPredicateSpec, TriggerPriorityOrderConfig,
113    TriggerRateLimitConfig, TriggerRegistryError, TriggerRetryConfig, TriggerSingletonConfig,
114    TriggerState, TriggerThrottleConfig, WorkerQueue, WorkerQueueClaimHandle,
115    WorkerQueueEnqueueReceipt, WorkerQueueJob, WorkerQueueJobState, WorkerQueuePriority,
116    WorkerQueueResponseRecord, WorkerQueueState, WorkerQueueSummary, DEFAULT_INBOX_RETENTION_DAYS,
117    TRIGGERS_LIFECYCLE_TOPIC, TRIGGER_ATTEMPTS_TOPIC, TRIGGER_CANCEL_REQUESTS_TOPIC,
118    TRIGGER_DLQ_TOPIC, TRIGGER_INBOX_CLAIMS_TOPIC, TRIGGER_INBOX_ENVELOPES_TOPIC,
119    TRIGGER_INBOX_LEGACY_TOPIC, TRIGGER_OPERATION_AUDIT_TOPIC, TRIGGER_OUTBOX_TOPIC,
120    TRIGGER_TEST_FIXTURES, WORKER_QUEUE_CATALOG_TOPIC,
121};
122pub use trust_graph::{
123    append_active_trust_record, append_trust_record, query_trust_records,
124    resolve_agent_autonomy_tier, summarize_trust_records, topic_for_agent, AutonomyTier,
125    TrustAgentSummary, TrustOutcome, TrustQueryFilters, TrustRecord, OPENTRUSTGRAPH_SCHEMA_V0,
126    TRUST_GRAPH_GLOBAL_TOPIC, TRUST_GRAPH_TOPIC_PREFIX,
127};
128pub use value::*;
129pub use vm::*;
130
131/// Lex, parse, type-check, and compile source to bytecode in one call.
132/// Bails on the first type error. For callers that need diagnostics
133/// rather than early exit, use `harn_parser::check_source` directly
134/// and then call `Compiler::new().compile(&program)`.
135pub fn compile_source(source: &str) -> Result<Chunk, String> {
136    let program = harn_parser::check_source_strict(source).map_err(|e| e.to_string())?;
137    Compiler::new().compile(&program).map_err(|e| e.to_string())
138}
139
140pub fn json_schema_for_type_expr(type_expr: &harn_parser::TypeExpr) -> Option<serde_json::Value> {
141    let schema = compiler::Compiler::type_expr_to_schema_value(type_expr)?;
142    let json_schema = schema::schema_to_json_schema_value(&schema).ok()?;
143    Some(llm::vm_value_to_json(&json_schema))
144}
145
146pub fn json_schema_for_typed_params(params: &[harn_parser::TypedParam]) -> serde_json::Value {
147    let mut properties = serde_json::Map::new();
148    let mut required = Vec::new();
149
150    for param in params {
151        let param_schema = param
152            .type_expr
153            .as_ref()
154            .and_then(json_schema_for_type_expr)
155            .unwrap_or_else(|| serde_json::json!({}));
156        if param.default_value.is_none() {
157            required.push(serde_json::Value::String(param.name.clone()));
158        }
159        properties.insert(param.name.clone(), param_schema);
160    }
161
162    let mut schema = serde_json::Map::new();
163    schema.insert(
164        "type".to_string(),
165        serde_json::Value::String("object".to_string()),
166    );
167    schema.insert(
168        "properties".to_string(),
169        serde_json::Value::Object(properties),
170    );
171    if !required.is_empty() {
172        schema.insert("required".to_string(), serde_json::Value::Array(required));
173    }
174    serde_json::Value::Object(schema)
175}
176
177/// Reset all thread-local state that can leak between test runs.
178pub fn reset_thread_local_state() {
179    llm::reset_llm_state();
180    llm_config::clear_user_overrides();
181    http::reset_http_state();
182    event_log::reset_active_event_log();
183    stdlib::reset_stdlib_state();
184    connectors::clear_active_connector_clients();
185    orchestration::clear_runtime_hooks();
186    triggers::clear_dispatcher_state();
187    triggers::clear_trigger_registry();
188    events::reset_event_sinks();
189    agent_events::reset_all_sinks();
190    agent_sessions::reset_session_store();
191    mcp_registry::reset();
192}