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