tools tier

tools-ask-ai-core

Shared client for the multi-AI bridge (ask-chatgpt / ask-gemini / ask-ais)

Shared client for the multi-AI bridge (ask-chatgpt / ask-gemini / ask-ais)

Tiertools
Roleunclassified (baselined)
Pathcrates/tools/ask-ai-core
Edition2021
Targetstools_ask_ai_core
Public items43 across 1 module
Tests31

What it is for

Shared client for the multi-AI bridge.

Exposes:

endpoint at /api/ask-{chatgpt,gemini}.

(no async runtime required). Returns per-provider AskResponse entries; the caller interprets success/failure per the Gate 1.5 Round 1 Q4 decision (tools-ask-ais exit code semantics).

Capabilities

verb:ask

Shared client for the multi-AI bridge.

Item
fn ask(api_url : & str, api_key : & str, req : & AskRequest) -> AskResponse
fn ask_with_recovery(api_url : & str, api_key : & str, req : & AskRequest) -> AskResponse
fn ask_many(api_url : & str, api_key : & str, providers : & AiProvider, req : & AskRequest,) -> Vec <AskResponse>

verb:busy

Shared client for the multi-AI bridge.

Item
fn busy_retry_after(body : & serde_json::Value, max_wait_secs : u64) -> Option <Duration>

verb:constants

Shared client for the multi-AI bridge.

Item
pub const DEFAULT_API_URL: & str
pub const DEFAULT_API_KEY: & str
pub const DEFAULT_TIMEOUT_SECS: u64
pub const COLLECT_TIMEOUT_SECS: u64
pub const DEFAULT_MAX_BUSY_WAIT_SECS: u64
pub const BUSY_POLL_CEILING_SECS: u64

verb:default

Shared client for the multi-AI bridge.

Item
fn default_api_url() -> String
fn default_api_key() -> String

verb:encode

Shared client for the multi-AI bridge.

Item
fn encode_image(path : & str) -> Result <ImageAttachment, AskError>

verb:max

Shared client for the multi-AI bridge.

Item
fn max_busy_wait_secs() -> u64

verb:session

Shared client for the multi-AI bridge.

Item
fn session_id() -> String

AiProvider

Shared client for the multi-AI bridge.

Item
pub enum AiProvider
AiProvider :: fn as_str(self) -> & 'static str
AiProvider :: fn command_type(self) -> & 'static str
AiProvider :: fn endpoint_path(self) -> & 'static str
AiProvider :: fn display_label(self) -> & 'static str
AiProvider :: fn parse(s : & str) -> Option <Self>

AskError

Shared client for the multi-AI bridge.

Item
pub enum AskError

AskRequest

Shared client for the multi-AI bridge.

Item
pub struct AskRequest

AskResponse

Shared client for the multi-AI bridge.

Item
pub struct AskResponse
AskResponse :: fn ok(provider : AiProvider, text : String, duration_ms : u128) -> Self
AskResponse :: fn error(provider : AiProvider, status : AskStatus, error : String, duration_ms : u128,) -> Self
fn format_single(resp : & AskResponse) -> Result <String, String>
fn format_labeled(responses : & AskResponse) -> String
fn format_json(responses : & AskResponse) -> String
fn exit_code_for(responses : & AskResponse) -> i32

AskStatus

Shared client for the multi-AI bridge.

Item
pub enum AskStatus
AskStatus :: fn as_str(self) -> & 'static str
AskStatus :: fn is_success(self) -> bool
fn is_collectible(status : AskStatus, error : Option <& str>) -> bool

ImageAttachment

Shared client for the multi-AI bridge.

Item
pub struct ImageAttachment

precheck (other)

Advisory client-side DLP pre-check (Sprint 3.6 T9).

Item
pub const POLICY_ENV: & str
fn load_policy_from_path(path : Option <& str>) -> Result <ScreenPolicy, String>
fn load_policy() -> Result <ScreenPolicy, String>
fn resolve_prompt_arg(message : & str) -> Result <String, String>

CliGateDecision

Advisory client-side DLP pre-check (Sprint 3.6 T9).

Item
pub enum CliGateDecision

Precheck

Advisory client-side DLP pre-check (Sprint 3.6 T9).

Item
pub enum Precheck
fn precheck_prompt(prompt : & str, policy : & ScreenPolicy) -> Precheck
fn cli_precheck(prompt : & str, force_send : bool) -> CliGateDecision

How to use it

No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.

Module structure

tools_ask_ai_core

Public surface

`crate root`

ItemWhat it is
pub const DEFAULT_API_URL: & str
pub const DEFAULT_API_KEY: & str
pub const DEFAULT_TIMEOUT_SECS: u64300s: consensus-scale prompts on slow provider modes routinely outlast the old 180s (three timeouts on 2026-08-08 alone)
pub const COLLECT_TIMEOUT_SECS: u64Budget for the post-timeout collect retry (extension-side poll).
pub const DEFAULT_MAX_BUSY_WAIT_SECS: u64How long to keep waiting for a provider tab another session holds, before giving up
pub const BUSY_POLL_CEILING_SECS: u64Longest single sleep between retries while a provider tab is held
pub enum AiProvider
AiProvider :: fn as_str(self) -> & 'static str
AiProvider :: fn command_type(self) -> & 'static strThe extension-side command type string.
AiProvider :: fn endpoint_path(self) -> & 'static strThe bridge HTTP endpoint path (sans scheme/host).
AiProvider :: fn display_label(self) -> & 'static strDisplay label used in multi-provider output (=== CHATGPT ===).
AiProvider :: fn parse(s : & str) -> Option <Self>
pub struct AskRequest
pub struct ImageAttachment
pub enum AskStatusStatus of a single-provider ask.
AskStatus :: fn as_str(self) -> & 'static str
AskStatus :: fn is_success(self) -> bool
pub struct AskResponse
AskResponse :: fn ok(provider : AiProvider, text : String, duration_ms : u128) -> Self
AskResponse :: fn error(provider : AiProvider, status : AskStatus, error : String, duration_ms : u128,) -> Self
pub enum AskError
fn encode_image(path : & str) -> Result <ImageAttachment, AskError>Load and base64-encode an image, returning an ImageAttachment ready to attach to an AskRequest
fn default_api_url() -> StringRead the bridge URL from ASK_CHATGPT_API env var, falling back to the default localhost bridge.
fn default_api_key() -> StringRead the bridge API key from ASK_CHATGPT_KEY env var, falling back to the dev default.
fn session_id() -> StringSynchronously ask a single AI provider
fn busy_retry_after(body : & serde_json::Value, max_wait_secs : u64) -> Option <Duration>How long to wait before retrying, given a 409 body — or None if this is not a provider-busy refusal and so not something waiting can fix
fn max_busy_wait_secs() -> u64The ceiling on total time spent waiting out other sessions.
fn ask(api_url : & str, api_key : & str, req : & AskRequest) -> AskResponse
fn is_collectible(status : AskStatus, error : Option <& str>) -> boolTrue when a failed ask is worth a collect retry: the send reached the provider and generation likely FINISHED after our clock ran out — a timeout, a gateway 504, or a bridge-side timeout message
fn ask_with_recovery(api_url : & str, api_key : & str, req : & AskRequest) -> AskResponseask plus the timeout-recovery pass: when the ask fails collectibly (see is_collectible), one collect_response attempt recovers the answer stranded in the provider tab
fn ask_many(api_url : & str, api_key : & str, providers : & AiProvider, req : & AskRequest,) -> Vec <AskResponse>Fan out to multiple providers in parallel (one OS thread per provider)
fn format_single(resp : & AskResponse) -> Result <String, String>Format a single-provider response as plain text (for ask-chatgpt / tools-ask-gemini)
fn format_labeled(responses : & AskResponse) -> StringFormat multi-provider responses as labeled blocks (for tools-ask-ais default mode)
fn format_json(responses : & AskResponse) -> StringFormat multi-provider responses as a single JSON object keyed by provider name (for tools-ask-ais --json)
fn exit_code_for(responses : & AskResponse) -> i32Pick an appropriate process exit code for tools-ask-ais responses per Gate 1.5 Round 1 Q4: total success or partial success → 0, total failure → 1.

`precheck`

ItemWhat it is
pub const POLICY_ENV: & strEnv var naming the local policy TOML for the client pre-check (same file format the server loads; see the platform-privacy-scan-api README).
pub enum PrecheckOutcome of the local advisory pre-check.
fn load_policy_from_path(path : Option <& str>) -> Result <ScreenPolicy, String>Load the pre-check policy from an explicit path, or the built-in default policy when path is None
fn load_policy() -> Result <ScreenPolicy, String>Load the pre-check policy from the DLP_GATE_POLICY env var
fn precheck_prompt(prompt : & str, policy : & ScreenPolicy) -> PrecheckRun the advisory pre-check on prompt against policy
pub enum CliGateDecisionThe full CLI-side decision: load the local policy (env), pre-check, and fold in --force-send
fn cli_precheck(prompt : & str, force_send : bool) -> CliGateDecisionApply the advisory pre-check for a CLI invocation
fn resolve_prompt_arg(message : & str) -> Result <String, String>Resolve a CLI prompt argument: - reads the prompt from STDIN

Re-exports. Exported here, defined elsewhere.

ExportDefined in
ScreenPolicyinfrastructure_dlp_detect::ScreenPolicy

Boundary

Reaches into infrastructure.

Shares tier tools with 84 other crates: tools-advisory-reach, tools-archive-guard, tools-artifact-scaffold, tools-ask-ais, tools-ask-gemini, tools-book, tools-book-report, tools-boundary-scan, … (84 total).

_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._

Where it sits

Tier (ontology)tools
Architectural role (taxonomy)unclassified (baselined)
Locationcrates/tools/ask-ai-core
Vocabulary in force (lexicon)current

Tier flow. Which tiers this crate's own edges cross.

flowchart LR
  n_tools["tools"] --> n_infrastructure["infrastructure"]

Dependencies

Runtime, in this workspace.

CrateTierOptionalOnly on
`infrastructure-dlp-detect`infrastructurenoalways

Runtime, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
base64^0.22noalways
serde^1derivenoalways
serde_json^1noalways
thiserror^2noalways
ureq^2.10noalways

Development. None.

Build. None.

Depended on by. 2 workspace crates.

Signal flow — what reaches this crate, and what it reaches.

flowchart LR
  n_tools_ask_ais["tools-ask-ais"] -->|uses| SELF
  n_tools_ask_gemini["tools-ask-gemini"] -->|uses| SELF
  SELF["tools-ask-ai-core"]
  SELF -->|runtime| n_infrastructure_dlp_detect["infrastructure-dlp-detect"]
  classDef self fill:#1f883d,stroke:#1f883d,color:#fff;
  class SELF self;

Feature flags

No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.

Targets

KindNameSource
libtools_ask_ai_core`src/lib.rs`

Error model

Error typeNamed by
AskErrorencode_image

Operational characteristics

PropertyEvidence
async public surfacenone detected
async runtimenone detected
database accessnone detected
network I/Onone detected
unsafe codenone detected
environment variablesyes

No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.

Configuration

VariableRead in
ASK_AI_MAX_WAIT_SECSsrc/lib.rs
ASK_AI_SESSION_IDsrc/lib.rs
ASK_CHATGPT_APIsrc/lib.rs
ASK_CHATGPT_KEYsrc/lib.rs

2 workspace crates depend on this one: tools-ask-ais, tools-ask-gemini.

Verification

KindCount
Unit tests31
Integration tests0
Examples0
Doctests0

Evidence by module. How often each public module is named by something executable.

ModuleTestsExamplesConsumers
crate root26019
precheck806

What the tests establish, by name:

Documentation coverage

MeasureDocumentedTotal
Public items with rustdoc2943
Public modules with a //! block11
pie showData
    title Public items with rustdoc
    "Documented" : 29
    "No rustdoc detected" : 14

Metrics

MetricValue
Rust source files2
Source lines1306
Code lines978
Public API items43
Public modules1
Tests31
Examples0
Cargo features0
Direct runtime dependencies6
Workspace reverse dependencies2
pie showData
    title Public API by kind
    "constant" : 7
    "enum" : 5
    "function" : 19
    "method" : 9
    "struct" : 3
pie showData
    title Rust source composition
    "Code" : 978
    "Blank or comment" : 328

Generation

Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.

All tools · Manual