Skip to main content

deepstrike_sdk/
lib.rs

1pub mod governance;
2pub mod harness;
3pub mod harness_loop;
4pub mod knowledge;
5pub mod memory;
6pub mod providers;
7pub mod run_event;
8pub mod runtime;
9pub mod safety;
10pub mod signals;
11pub mod tools;
12
13#[cfg(test)]
14mod tests;
15
16pub use deepstrike_core::context::measurement::{MeasurementConfidence, MeasurementSource};
17pub use deepstrike_core::context::renderer::RenderedContext;
18pub use deepstrike_core::governance::permission::PermissionAction;
19pub use deepstrike_core::governance::quota::ResourceQuota;
20// Session entropy (heartbeat watch source): the kernel emits `entropy_sample` /
21// `entropy_alert` observations through the shared JSON ABI; these types are for hosts
22// configuring the watch (`set_entropy_watch` / `configure_run.entropy_watch`) or folding
23// their own samples when driving the kernel manually.
24pub use deepstrike_core::mm::memory::{
25    MemoryAuthor, MemoryKind, MemoryProvenance, MemoryQuery, MemoryRecall, MemoryRecord,
26    MemoryScope, MemoryTrustLevel,
27};
28pub use deepstrike_core::runtime::kernel::wire::MemoryPolicy;
29pub use deepstrike_core::{EntropySample, EntropyTracker, EntropyWatchConfig};
30// Workflow surface (DELIBERATE floor, not a gap): the Rust SDK has no `run_workflow` driver — the
31// node/python/wasm SDKs own async node execution. These re-exports are for MANUAL driving: build a
32// spec with the templates, hold a `WorkflowRun` (a pure state machine), call `ready_batch()` /
33// `spawn_info()` / `record_completion()` from your own executor. Everything the drivers do is
34// reachable this way; a batteries-included Rust driver lands only when a real consumer needs it.
35pub use deepstrike_core::orchestration::workflow::{JudgeMatch, WorkflowRun, WorkflowSpawnInfo};
36pub use deepstrike_core::orchestration::workflow::{
37    WorkflowNode, WorkflowSpec, fanout_synthesize, gen_eval, generate_and_filter, verify_rules,
38};
39pub use governance::{Governance, GovernanceVerdict};
40pub use harness::{Criterion, CriterionResult, Verdict};
41pub use harness_loop::{
42    AttemptBody, AttemptBodyContext, AttemptBodyEvent, AttemptBodyStream, AttemptJudge,
43    AttemptLoop, AttemptLoopEvent, AttemptLoopStream, AttemptOutcome, AttemptOutcomeKind,
44    AttemptRequest, CarryContext, CarryPolicy, ContinueSession, DigestFn, DigestFuture,
45    FreshWithDigest, FreshWithFeedback, HybridJudge, JudgeContext, JudgeResult, LlmEvalJudge,
46    PassHook, PassHookFuture, PreparedAttempt, RuntimeAttemptBody, StopPolicy, VerdictFn,
47    VerdictFnJudge,
48};
49pub use knowledge::KnowledgeSource;
50pub use memory::{
51    DurableMemory, InMemoryMemoryStore, MemorySearchOptions, MemoryStore, WorkingMemory,
52};
53pub use providers::RuntimePolicy;
54pub use providers::anthropic::AnthropicProvider;
55pub use providers::openai::{OpenAIProvider, deepseek, kimi, minimax, ollama, qwen};
56pub use providers::request_plan::{
57    CostObservation, NormalizedProviderUsage, PricingRates, PricingSnapshot,
58    ProviderRequestEndpoint, ProviderRequestPlan, ProviderUsage, RecordedPromptMeasurement,
59    RequestPlanError, UnpricedReason, measurement_for_plan, normalize_provider_usage,
60    price_provider_usage, record_prompt_measurement,
61};
62pub use providers::{
63    LLMProvider, ProviderError, ProviderErrorKind, ProviderRunState, ProviderToolSpec, StreamEvent,
64    TokenUsage,
65};
66pub use run_event::RunEvent;
67pub use runtime::eval::{Criterion as EvalCriterion, Verdict as EvalVerdict};
68pub use runtime::eval::{build_eval_messages, judge, parse_verdict, verdict_output_schema};
69pub use runtime::replay_fixture::{
70    extract_recorded_messages, extract_recorded_messages_from_entries,
71};
72pub use runtime::replay_provider::{ReplayProvider, ReplayProviderOpts};
73pub use runtime::{
74    CanonicalCheckpoint, CanonicalCheckpointCandidate, CanonicalCommit, CanonicalKernel,
75    CanonicalPreparation,
76};
77pub use runtime::{
78    ChainedCredentialVault, CredentialVault, EnvCredentialVault, InMemoryCredentialVault,
79};
80pub use runtime::{
81    DEFAULT_NATIVE_SIGNAL_POLICY, GovernancePolicy, MemoryWriteRateLimit, NativeOsProfile,
82    OsProfile, SchedulerPolicyConfig, SignalPolicy, assert_native_profile,
83    default_native_governance_policy, os_profile,
84};
85pub use runtime::{ExecutionPlane, LocalExecutionPlane};
86pub use runtime::{FilePayloadStore, PayloadStore};
87pub use runtime::{FileSessionLog, InMemorySessionLog, SessionEntry, SessionLog};
88pub use runtime::{
89    KernelReliability, MilestoneEvaluationContext, MilestoneEvaluationHandler, MilestonePolicy,
90    RuntimeOptions, RuntimeRunner, collect_text,
91};
92// Durable transaction capability (Canonical Kernel ABI §9.1). `FileKernelJournal` is the
93// cross-process-atomic reference implementation; `InMemoryKernelJournal` is dev/test only.
94pub use runtime::{
95    CheckpointCandidate, FileKernelJournal, InMemoryKernelJournal, InstalledCheckpoint,
96    JournalAppendReceipt, JournalEntry, JournalError, JournalHead, JournalPruneReceipt,
97    JournalRecordInput, JournalResult, KernelJournal,
98};
99pub use runtime::{McpProxyPlane, McpServerConfig};
100pub use runtime::{
101    PermissionRequest, PermissionRequestHandler, PermissionResponse, RunContext,
102    ToolSuspendHandler, ToolSuspendRequest,
103};
104pub use runtime::{ProcessSandboxPlane, SandboxOptions};
105pub use runtime::{RemoteVpcOptions, RemoteVpcPlane};
106pub use safety::{Permission, PermissionDecision, PermissionManager, PermissionMode};
107pub use signals::{
108    GatewayReceiver, RuntimeSignal, ScheduledPrompt, SignalClaim, SignalDeliveryReceipt,
109    SignalGateway, SignalSource,
110};
111pub use tools::{
112    RegisteredTool, SafeToolResult, TextToolSession, ToolChunk, ToolEnvelope, ToolEnvelopeFail,
113    ToolEnvelopeOk, ToolSession, ToolStep, execute_tools, fail, ok, read_file_tool, safe_tool,
114    tool_fail, validate_tool_arguments,
115};
116
117#[derive(Debug, thiserror::Error)]
118pub enum Error {
119    #[error("provider error: {0}")]
120    Provider(String),
121    #[error(transparent)]
122    ProviderFailure(#[from] providers::ProviderError),
123    #[error("tool error: {0}")]
124    Tool(String),
125    #[error("io error: {0}")]
126    Io(#[from] std::io::Error),
127    #[error("tool execution failed: {output}")]
128    ToolExecutionFailed {
129        output: String,
130        is_fatal: bool,
131        error_kind: Option<deepstrike_core::types::message::ToolErrorKind>,
132    },
133    /// Tool author signalled a structured failure with optional machine-readable `code` and a
134    /// self-correcting `hint`. Parity with the Node/Python `ToolError` + `safe_tool` envelope:
135    /// surfaced to the model as JSON `{message, code?, hint?}` (via `format_tool_error`) so the
136    /// agent can branch on `code` instead of pattern-matching a free-form string.
137    #[error("{output}")]
138    ToolFail {
139        output: String,
140        code: Option<String>,
141        hint: Option<String>,
142        is_fatal: bool,
143        error_kind: Option<deepstrike_core::types::message::ToolErrorKind>,
144    },
145    #[error("{0}")]
146    Other(String),
147}
148
149/// Error-aware serialization for tool-execution error paths. Replaces `e.to_string()` at the
150/// sites that hand the model a failure message:
151///
152/// - `Error::Tool(s)` → `s` (drops the `"tool error: "` prefix from `e.to_string()`).
153/// - `Error::ToolExecutionFailed { output, .. }` → `output` (drops the `"tool execution failed: "` prefix).
154/// - `Error::ToolFail { output, code:None, hint:None, .. }` → `output`.
155/// - `Error::ToolFail { output, code, hint, .. }` (either set) → JSON `{message, code?, hint?}`.
156/// - everything else → `e.to_string()` (the `thiserror`-formatted string).
157pub fn format_tool_error(e: &Error) -> String {
158    match e {
159        Error::Tool(s) => s.clone(),
160        Error::ToolExecutionFailed { output, .. } => output.clone(),
161        Error::ToolFail {
162            output, code, hint, ..
163        } => {
164            if code.is_none() && hint.is_none() {
165                return output.clone();
166            }
167            let mut obj = serde_json::Map::with_capacity(3);
168            obj.insert(
169                "message".to_string(),
170                serde_json::Value::String(output.clone()),
171            );
172            if let Some(c) = code {
173                obj.insert("code".to_string(), serde_json::Value::String(c.clone()));
174            }
175            if let Some(h) = hint {
176                obj.insert("hint".to_string(), serde_json::Value::String(h.clone()));
177            }
178            serde_json::to_string(&serde_json::Value::Object(obj))
179                .unwrap_or_else(|_| output.clone())
180        }
181        _ => e.to_string(),
182    }
183}
184
185pub type Result<T> = std::result::Result<T, Error>;