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