///|
/// Text and optional context files sent to a provider CLI session.
///
/// The `context_files` collection preserves caller order. Codex adapters append
/// the paths to the prompt text, while OpenCode adapters forward them as
/// ordered local-file inputs. Callers should resolve relative paths against
/// their workspace before constructing a prompt.
pub struct Prompt {
text : String
context_files : ReadOnlyArray[@path.Path]
} derive(Debug, Eq)
///|
/// Creates a provider-neutral prompt without changing text-only callers.
///
/// ```check
/// let prompt = Prompt::Prompt("review", context_files=[
/// @path.Path("src/main.mbt"),
/// ])
/// assert_eq(prompt.text, "review")
/// assert_eq(prompt.context_files.length(), 1)
/// ```
pub fn Prompt::Prompt(
text : String,
context_files? : ReadOnlyArray[@path.Path] = [],
) -> Prompt {
{ text, context_files }
}
///|
/// Opaque provider continuation handle.
///
/// A continuation captures provider-owned resume behavior. Pass it to
/// `Cli::continue_session`; callers do not inspect or construct its identifier.
pub struct Continuation {
priv resume_session : () -> &CliSession
}
///|
/// Creates an opaque continuation handle from provider-owned resume behavior.
pub fn Continuation::Continuation(
resume_session : () -> &CliSession,
) -> Continuation {
{ resume_session, }
}
///|
/// Final text, session metadata, changed files, and continuation returned by a
/// completed prompt.
///
/// `session_id` is populated when the provider exposes its thread identifier.
/// `changed_files` contains completed Codex patch paths and is empty for the
/// OpenCode adapter because its current event model has no reliable change set.
pub struct FinalResponse {
text : String
session_id : String?
changed_files : ReadOnlyArray[@path.Path]
continuation : Continuation?
}
///|
/// Creates a final response with optional provider metadata.
///
/// ```check
/// let response = FinalResponse::FinalResponse(
/// "done",
/// session_id="session-1",
/// )
/// assert_eq(response.text, "done")
/// assert_eq(response.session_id, Some("session-1"))
/// ```
pub fn FinalResponse::FinalResponse(
text : String,
session_id? : String,
changed_files? : ReadOnlyArray[@path.Path] = [],
continuation? : Continuation,
) -> FinalResponse {
{ text, session_id, changed_files, continuation }
}
///|
/// A live provider CLI session.
///
/// `id` exposes the provider thread or session identifier when available, and
/// `continuation` returns an opaque handle after a provider has completed a
/// prompt. Provider errors pass through unchanged.
///
/// Cancelling the task running `prompt` cancels the provider call and propagates
/// the cancellation error after provider cleanup.
pub(open) trait CliSession {
/// Returns the provider thread or session identifier when available.
fn id(Self) -> String?
/// Returns an opaque handle for resuming this provider session when available.
fn continuation(Self) -> Continuation?
/// Sends a prompt and returns the provider's completed final response.
async fn prompt(Self, Prompt) -> FinalResponse
}
///|
/// Provider-neutral entry point for starting or resuming CLI sessions.
///
/// Use `start` for a fresh provider session or `continue_session` with the
/// continuation from a previous `FinalResponse`.
pub struct Cli {
priv start_session : () -> &CliSession
}
///|
/// Creates a CLI adapter from provider-specific session factories.
///
/// The factory is called when `start` is invoked, so provider-native options
/// remain owned by the selected adapter.
pub fn Cli::Cli(start : () -> &CliSession) -> Cli {
{ start_session: start }
}
///|
/// Starts a new provider session using the adapter's provider-native options.
pub fn Cli::start(self : Cli) -> &CliSession {
(self.start_session)()
}
///|
/// Resumes the provider session represented by an opaque continuation.
///
/// The continuation remains opaque and is consumed only by the selected
/// provider adapter.
pub fn Cli::continue_session(
_self : Cli,
continuation : Continuation,
) -> &CliSession {
(continuation.resume_session)()
}