/** * log10x_start — orientation tool. * * THE tool the agent calls FIRST whenever a user expresses any cost-cutting * goal or open-ended platform question (save X%, cut my bill, where do I * start, what should I do, how can you help, first session against a fresh * MCP install). * * The orientation envelope returns three explicit compliance levers the * agent must obey: * * 1. must_render_verbatim — pre-rendered markdown the agent MUST surface * to the user as-is (no summarising, no pre-picking, no editorial). * 2. must_ask_user — a structured question + numbered options the * agent MUST ask the user before any follow-up tool call. * 3. forbidden_next_actions — tool names the agent MUST NOT call until * the user has answered the must_ask_user question. * * Capability detection reuses the same three doctor probes (Retriever * resolution, gateway auth, Reporter tier metric counts) to place the user * on the ladder: Dev CLI → Reporter → Receiver → Retriever. Receiver-tier * discrimination from Reporter is best-effort here — doctor.ts collapses * both into edge/cloud — so we surface a `receiver_discrimination` hint * rather than guessing. */ import { z } from 'zod'; import { type SiemLensResolution } from '../lib/siem/lens.js'; import { type Environments } from '../lib/environments.js'; import { type StructuredOutput } from '../lib/output-types.js'; export type Tier = 'dev' | 'reporter' | 'receiver' | 'retriever'; export declare const IntentHintSchema: z.ZodOptional>; export declare const SessionStateSchema: z.ZodOptional>; export declare const log10xStartSchema: { intent_hint: z.ZodOptional>; session_state: z.ZodOptional>; siem_lens: z.ZodOptional>; }; export interface CapabilitySummary { /** Reporter tier emitting metrics so cost attribution + savings tools work. */ cost_attribution_available: boolean; /** Receiver tier installed (in-path) so compact/sample/drop CAN take effect. */ compact_installable: boolean; /** Receiver tier emits the `routeState` marker so the SIEM can tier_down by routing rule. */ tier_down_available: boolean; /** Retriever reachable to read the offloaded cohort from the overflow S3 bucket. */ forensic_query_available: boolean; /** Customer-owned offload S3 bucket detected (offload action target). */ offload_ready: boolean; /** Any SIEM connector credentials detected for dependency_check / pattern_examples. */ siem_query_available: boolean; /** True when Retriever vs Receiver could not be discriminated (best-effort). */ receiver_discrimination_uncertain: boolean; } export interface ActionMenuItem { /** Stable action identifier the user picks by number. */ action: 'run_poc' | 'estimate_savings' | 'investigate_spike' | 'forensic_query' | 'install_receiver' | 'install_retriever' | 'explore_receiver' | 'explore_overflow' | 'orient_only'; /** Short label rendered to the user in the menu. */ label: string; /** Whether the user's current tier supports this action without further setup. */ applicable: boolean; /** When `applicable=false`, the reason — e.g. "requires Receiver, you are at Reporter". */ gated_reason?: string; /** Tool the agent should call once the user picks this menu item. */ routes_to: string; } export interface JourneyPhase { /** Phase ordinal 1..5. */ phase: number; /** Short name rendered in the user-facing markdown. */ name: string; /** One-line description of what this phase delivers. */ description: string; /** Where the user is right now relative to this phase. */ current_status: 'complete' | 'in_progress' | 'not_started' | 'blocked_by_prior_phase'; } export interface MustAskUser { question: string; options: string[]; } export interface Log10xStartEnvelope { tier: Tier; siem_detected: string | null; capability_summary: CapabilitySummary; action_menu: ActionMenuItem[]; journey_phases: JourneyPhase[]; must_render_verbatim: string; must_ask_user: MustAskUser; forbidden_next_actions: string[]; /** Intent hint as resolved (`orient` when caller passed undefined). */ intent_hint: 'cost' | 'forensic' | 'install' | 'orient'; /** Present when a what-if destination lens is in effect (siem_lens arg). */ siem_lens?: string; /** Actual destination, canonical form, when a lens is in effect. */ siem_actual?: string | null; /** How the effective destination was chosen, when a lens is in effect. */ siem_lens_basis?: 'requested' | 'detected' | 'none'; } /** Resolve the customer's tier from the three probes. */ declare function resolveTier(args: { gatewayOk: boolean; reporterTier: 'edge' | 'cloud' | null; receiverInPath: boolean; retrieverOk: boolean; }): Tier; /** Build the capability summary from the probes. */ declare function buildCapabilities(args: { tier: Tier; gatewayOk: boolean; reporterTier: 'edge' | 'cloud' | null; receiverInPath: boolean; receiverUncertain: boolean; retrieverOk: boolean; siemDetected: string | null; }): CapabilitySummary; /** * Build the action menu, gated by current capabilities AND by the gates the * routed tool itself applies. * * The capability gate answers "does the user's tier support this action". It * is not the same question as "will routes_to actually run", and on a keyless * boot the two disagreed: the demo dataset answers the tier probes, so * cost_attribution_available came back true and investigate_spike shipped with * `applicable: true` — routing the agent to log10x_top_patterns, which the demo * gate then refuses with a not_configured envelope. The menu was the thing that * sent the agent into the refusal. * * So every item is re-checked against `toolUnavailableReason(routes_to)`, the * same predicate wrap() uses. An item the routed tool would refuse is not * applicable, whatever the tier says, and its gated_reason names a tool that IS * callable in this state. */ declare function buildActionMenu(caps: CapabilitySummary, tier: Tier, envs?: Environments): ActionMenuItem[]; /** * Fold the routed tool's own gates into each item. Capability-gated items keep * their existing reason: "install the Reporter first" is more actionable than * "the tool would refuse", and both are true. */ declare function applyToolGates(menu: ActionMenuItem[], envs?: Environments): ActionMenuItem[]; /** The tier-capability half of the menu, before the routed tools' own gates. */ declare function buildTierMenu(caps: CapabilitySummary, tier: Tier): ActionMenuItem[]; /** Build the 5-phase journey based on current tier. */ declare function buildJourneyPhases(tier: Tier, caps: CapabilitySummary): JourneyPhase[]; /** Render the must_render_verbatim markdown. */ declare function renderVerbatim(args: { tier: Tier; siemDetected: string | null; caps: CapabilitySummary; menu: ActionMenuItem[]; phases: JourneyPhase[]; intent: 'cost' | 'forensic' | 'install' | 'orient'; lens?: SiemLensResolution; }): string; /** Tools the agent MUST NOT call until the user answers must_ask_user. */ declare function buildForbiddenNextActions(): string[]; export declare function executeLog10xStart(args: { intent_hint?: 'cost' | 'forensic' | 'install' | 'orient'; session_state?: 'fresh' | 'midway' | 'returning'; siem_lens?: string; }): Promise; /** Export so log10x-start.test.ts can call buildActionMenu / buildCapabilities directly. */ export declare const _internals: { resolveTier: typeof resolveTier; buildCapabilities: typeof buildCapabilities; buildActionMenu: typeof buildActionMenu; buildTierMenu: typeof buildTierMenu; applyToolGates: typeof applyToolGates; buildJourneyPhases: typeof buildJourneyPhases; renderVerbatim: typeof renderVerbatim; buildForbiddenNextActions: typeof buildForbiddenNextActions; }; export {};