72 lines
2.8 KiB
Text
72 lines
2.8 KiB
Text
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||
|
|
|
||
|
|
// crafter-debug, the client agents drive an app with. Run is the whole
|
||
|
|
// program but for the transport: main hands it a Connector that reaches an
|
||
|
|
// instance over QUIC, and tests hand it one that reaches a Session in the
|
||
|
|
// same process.
|
||
|
|
//
|
||
|
|
// Exit codes:
|
||
|
|
// 0 done
|
||
|
|
// 2 a usage error, or no debug build yet (the launcher's stub)
|
||
|
|
// 3 no instance to talk to
|
||
|
|
// 4 the app and this client speak different protocols
|
||
|
|
// 5 timed out
|
||
|
|
// 6 the app answered with an error
|
||
|
|
// 1 is left to the launcher and `flatpak run` failing.
|
||
|
|
export module Crafter.Debug.Cli:Client;
|
||
|
|
import std;
|
||
|
|
import Crafter.Debug.Core;
|
||
|
|
|
||
|
|
export namespace Crafter::Debug::Cli {
|
||
|
|
inline constexpr std::int32_t exitOk = 0;
|
||
|
|
inline constexpr std::int32_t exitUsage = 2;
|
||
|
|
inline constexpr std::int32_t exitNoInstance = 3;
|
||
|
|
inline constexpr std::int32_t exitVersion = 4;
|
||
|
|
inline constexpr std::int32_t exitTimeout = 5;
|
||
|
|
inline constexpr std::int32_t exitError = 6;
|
||
|
|
|
||
|
|
struct CallError {
|
||
|
|
enum class Kind : std::uint8_t {
|
||
|
|
// No connection: the app is gone, or its port does not answer.
|
||
|
|
Unreachable,
|
||
|
|
// Connected, but no reply within the timeout.
|
||
|
|
TimedOut,
|
||
|
|
// The reply was not what the protocol says.
|
||
|
|
Broken,
|
||
|
|
};
|
||
|
|
Kind kind = Kind::Unreachable;
|
||
|
|
std::string message;
|
||
|
|
};
|
||
|
|
|
||
|
|
// One request to an instance. The reply is the last object it sends;
|
||
|
|
// objects before it are stream lines (`log --follow`), handed to
|
||
|
|
// `onLine`, which returns false to stop.
|
||
|
|
class Connection {
|
||
|
|
public:
|
||
|
|
virtual ~Connection() = default;
|
||
|
|
virtual std::expected<Value, CallError> Call(const Value& request, std::chrono::milliseconds timeout,
|
||
|
|
const std::function<bool(const Value& line)>& onLine) = 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
using Connector = std::function<std::unique_ptr<Connection>(const InstanceRecord& instance)>;
|
||
|
|
|
||
|
|
struct Environment {
|
||
|
|
Connector connect;
|
||
|
|
std::function<std::vector<Instance>()> list = ListInstances;
|
||
|
|
std::ostream* out = &std::cout;
|
||
|
|
std::ostream* err = &std::cerr;
|
||
|
|
// Where a screenshot without -o goes, relative paths included.
|
||
|
|
std::filesystem::path cwd = std::filesystem::current_path();
|
||
|
|
// Whether `lldb` exists here, for the attach command `debugger` prints.
|
||
|
|
std::function<bool()> haveLldb;
|
||
|
|
};
|
||
|
|
|
||
|
|
std::int32_t Run(std::span<const std::string_view> args, Environment& environment);
|
||
|
|
|
||
|
|
// The full reference an agent reads with `crafter-debug guide`.
|
||
|
|
std::string_view Guide();
|
||
|
|
|
||
|
|
// "30s", "500ms", "2m", "1h"; a bare number is seconds.
|
||
|
|
std::optional<std::chrono::milliseconds> ParseDuration(std::string_view text);
|
||
|
|
}
|