1#![recursion_limit = "256"]
2
3pub mod acp;
4mod bootstrap;
5pub mod cli;
6mod cli_bytecode;
7pub mod commands;
8mod compiler_context;
9#[doc(hidden)]
10pub mod dispatch;
11mod entrypoint;
12pub mod env_guard;
13mod eval_cli;
14mod exit;
15pub mod format;
16pub mod json_envelope;
17mod net;
18pub mod package;
19mod provider_bootstrap;
20mod provider_info;
21mod run_records;
22mod runtime;
23pub mod skill_loader;
24pub mod skill_provenance;
25mod source_exec;
26pub mod test_report;
27pub mod test_runner;
28pub mod test_timing;
29#[doc(hidden)]
30pub mod tests;
31mod typecheck_imports;
32pub use commands::dispatch_explain::DISPATCH_AUDIT_SCHEMA_VERSION;
33pub(crate) use compiler_context::{
34 compiler_for_source, compiler_with_imported_enum_candidates,
35 ensure_builtin_signatures_installed, imported_enum_candidates_for_source,
36};
37pub use harn_skills::{get_embedded_skill, list_embedded_skills, EmbeddedSkill, SkillFrontmatter};
38pub(crate) use self::entrypoint::*;
42pub(crate) use self::eval_cli::*;
43pub(crate) use self::exit::*;
44pub(crate) use self::provider_info::*;
45pub(crate) use self::run_records::*;
46pub(crate) use self::source_exec::*;
47
48use clap::{error::ErrorKind, CommandFactory, Parser as ClapParser};
49use std::path::{Path, PathBuf};
50use std::sync::{Arc, Once};
51use std::{env, fs, panic, process, thread};
52
53use cli::{
54 Cli, Command, CompletionShell, EvalCommand, GuardCommand, MergeCaptainCommand,
55 MergeCaptainMockCommand, ModelInfoArgs, PackageArtifactsCommand, PackageCacheCommand,
56 PackageCommand, PackageScaffoldCommand, PgCommand, ProviderCommand, SkillCommand,
57 SkillKeyCommand, SkillTrustCommand, TimeCommand, ToolCommand,
58};
59use harn_lexer::Lexer;
60use harn_modules::project_config;
61use harn_parser::{DiagnosticSeverity, Parser, TypeChecker};
62use runtime::{build_cli_runtime, cli_runtime_mode, CliRuntimeMode};
63pub const CLI_RUNTIME_STACK_SIZE: usize = 16 * 1024 * 1024;
64static BROKEN_PIPE_PANIC_HOOK: Once = Once::new();
65
66#[cfg(feature = "hostlib")]
67pub(crate) fn install_default_hostlib(vm: &mut harn_vm::Vm) {
68 let _ = harn_hostlib::install_default(vm);
69 harn_rules_hostlib::install(vm);
73}
74
75#[cfg(not(feature = "hostlib"))]
76pub(crate) fn install_default_hostlib(_vm: &mut harn_vm::Vm) {}
77
78pub fn run() {
81 install_broken_pipe_panic_hook();
82 harn_vm::initialize_runtime_assets();
83 let raw_args = normalize_serve_args(bootstrap::args_after_pre_runtime_command());
84 harn_vm::stdlib::force_link();
89
90 ensure_builtin_signatures_installed();
91
92 let runtime_mode = cli_runtime_mode(&raw_args);
93
94 let handle = thread::Builder::new()
95 .name("harn-cli".to_string())
96 .stack_size(CLI_RUNTIME_STACK_SIZE)
97 .spawn(move || {
98 let runtime = build_cli_runtime(runtime_mode);
99 runtime.block_on(async_main(raw_args, runtime_mode));
100 if let Err(error) = harn_vm::events::shutdown_otel_sink() {
107 eprintln!("[harn] OTel exporter shutdown failed: {error}");
108 }
109 })
110 .unwrap_or_else(|error| {
111 eprintln!("failed to start CLI runtime thread: {error}");
112 process::exit(1);
113 });
114
115 if let Err(payload) = handle.join() {
116 if runtime::is_broken_pipe_panic_payload(payload.as_ref()) {
117 process::exit(0);
118 }
119 std::panic::resume_unwind(payload);
120 }
121}
122
123fn install_broken_pipe_panic_hook() {
124 BROKEN_PIPE_PANIC_HOOK.call_once(|| {
125 let previous = panic::take_hook();
126 panic::set_hook(Box::new(move |info| {
127 if runtime::is_broken_pipe_panic_payload(info.payload()) {
128 return;
129 }
130 previous(info);
131 }));
132 });
133}