// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® export module Crafter.Review:Stream; import std; import :Json; // The claude CLI's stream-json, parsed, and a pass's status classified from // it. The patterns are hand-written scanners, case-insensitive with Unicode // folding (the Kelvin sign is a k) and Unicode-aware where \b and \s are. // // The stream is split into lines at \n only: the CLI writes U+2028 and \x1c // raw inside a JSON string, and a line cut there would be lost. export namespace Crafter::Review::Stream { // A Bash call of the database helper, alone or in a compound command: // this binary's ` sql`, with any path before it. bool IsSqlCall(std::string_view command); // The helper's ANSWERED line at the start of a line of the result. bool HasAnsweredLine(std::string_view text); // LIMIT_RE, AUTH_RE, CREDIT_RE: a rate limit, an authentication failure, // an organization out of API credit. bool LimitText(std::string_view text); bool AuthText(std::string_view text); bool CreditText(std::string_view text); // One pass over the NDJSON: the last result line, the last // rate_limit_event, the first session_id, usage totals, the first turn's // usage, tool-call forensics, system/init, each under its own key. Json ParseStream(std::string_view text); // structured_output, else the result text parsed as JSON, a // double-encoded string decoded; nullopt without a findings array. std::optional StructuredOutput(const Json& result); // ok | limit | credits | auth | timeout | error, and why. std::pair Classify(const Json& parsed, std::optional exitCode, std::string_view stderrText, bool timedOut = false); // {window: {utilization, resetsAt}} from a rate_limit_info: the CLI // reports a fraction (2026-09-17: five_hour 0.2), the pool thresholds are // percents. Json Windows(const Json& rate); }