// methods.mbt — upstream `src/methods.ts` mirror: the `LODY_EXTENSION_METHODS`
// wire names (7 requests + 3 notifications), `normalizeLodyExtensionMethod`,
// and every request/response/notification DTO the contract binds to those
// methods. `LodySubagentTask` itself lives in session.mbt (upstream
// `src/session.ts`).
///|
pub const LODY_RATE_LIMITS_GET : String = "_lody/rate_limits/get"
///|
pub const LODY_SESSION_STEER : String = "_lody/session/steer"
///|
pub const LODY_SESSION_GOAL : String = "_lody/session/goal"
///|
pub const LODY_SESSION_HISTORY_READ : String = "_lody/session/history/read"
///|
pub const LODY_SUBAGENTS_LIST : String = "_lody/subagents/list"
///|
pub const LODY_SUBAGENTS_CANCEL : String = "_lody/subagents/cancel"
///|
pub const LODY_SUBAGENTS_OUTPUT : String = "_lody/subagents/output"
///|
pub const LODY_SESSION_USAGE_UPDATE : String = "_lody/session/usage_update"
///|
pub const LODY_RATE_LIMITS_UPDATE : String = "_lody/rate_limits/update"
///|
pub const LODY_SESSION_STEER_APPLIED : String = "_lody/session/steer_applied"
///|
/// All ten `LODY_EXTENSION_METHODS` wire names, upstream declaration order
/// (7 requests then 3 notifications).
pub fn lody_extension_methods() -> Array[String] {
[
LODY_RATE_LIMITS_GET,
LODY_SESSION_STEER,
LODY_SESSION_GOAL,
LODY_SESSION_HISTORY_READ,
LODY_SUBAGENTS_LIST,
LODY_SUBAGENTS_CANCEL,
LODY_SUBAGENTS_OUTPUT,
LODY_SESSION_USAGE_UPDATE,
LODY_RATE_LIMITS_UPDATE,
LODY_SESSION_STEER_APPLIED,
]
}
///|
/// `normalizeLodyExtensionMethod`: prepend the `_` namespace prefix when the
/// method does not already start with one.
pub fn normalize_lody_extension_method(method_name : String) -> String {
if method_name.has_prefix("_") {
method_name
} else {
"_" + method_name
}
}
///|
/// `LodySteerRequest` — `_lody/session/steer` params. The prompt element
/// content shape is unconstrained upstream (generic `TPrompt`); it passes
/// through as opaque JSON — awaiting on-wire verification.
pub(all) struct LodySteerRequest {
session_id : String
prompt : Array[Json]
steer_id : String
} derive(Debug)
///|
pub fn LodySteerRequest::to_json(self : LodySteerRequest) -> Json {
Json::object(
Map::from_array([
("sessionId", Json::string(self.session_id)),
("prompt", Json::array(self.prompt)),
("steerId", Json::string(self.steer_id)),
]),
)
}
///|
pub fn LodySteerRequest::from_json(
raw : Json,
) -> Result[LodySteerRequest, String] {
try {
let ctx = "lody.steerRequest"
let fields = object_fields(raw, ctx)
Ok(LodySteerRequest::{
session_id: req_string(fields, ctx, "sessionId"),
prompt: req_array(fields, ctx, "prompt"),
steer_id: req_string(fields, ctx, "steerId"),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySteerResponse` — `_lody/session/steer` result.
pub(all) struct LodySteerResponse {
outcome : LodySteerOutcome
} derive(Eq, Debug)
///|
pub fn LodySteerResponse::to_json(self : LodySteerResponse) -> Json {
Json::object(
Map::from_array([("outcome", Json::string(self.outcome.to_wire()))]),
)
}
///|
pub fn LodySteerResponse::from_json(
raw : Json,
) -> Result[LodySteerResponse, String] {
try {
let ctx = "lody.steerResponse"
let fields = object_fields(raw, ctx)
Ok(LodySteerResponse::{
outcome: wire_of(
ctx,
"outcome",
LodySteerOutcome::of_wire(req_string(fields, ctx, "outcome")),
),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySteerApplied` — `_lody/session/steer_applied` notification payload.
pub(all) struct LodySteerApplied {
session_id : String
steer_id : String
} derive(Eq, Debug)
///|
pub fn LodySteerApplied::to_json(self : LodySteerApplied) -> Json {
Json::object(
Map::from_array([
("sessionId", Json::string(self.session_id)),
("steerId", Json::string(self.steer_id)),
]),
)
}
///|
pub fn LodySteerApplied::from_json(
raw : Json,
) -> Result[LodySteerApplied, String] {
try {
let ctx = "lody.steerApplied"
let fields = object_fields(raw, ctx)
Ok(LodySteerApplied::{
session_id: req_string(fields, ctx, "sessionId"),
steer_id: req_string(fields, ctx, "steerId"),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodyGoalControlRequest` — `_lody/session/goal` params, discriminated on
/// `action`: `set` carries an objective; pause/resume/clear do not.
pub(all) enum LodyGoalControlRequest {
Set(session_id~ : String, objective~ : String)
Pause(session_id~ : String)
Resume(session_id~ : String)
Clear(session_id~ : String)
} derive(Eq, Debug)
///|
pub fn LodyGoalControlRequest::to_json(self : LodyGoalControlRequest) -> Json {
match self {
Set(session_id~, objective~) =>
Json::object(
Map::from_array([
("action", Json::string("set")),
("sessionId", Json::string(session_id)),
("objective", Json::string(objective)),
]),
)
Pause(session_id~) =>
Json::object(
Map::from_array([
("action", Json::string("pause")),
("sessionId", Json::string(session_id)),
]),
)
Resume(session_id~) =>
Json::object(
Map::from_array([
("action", Json::string("resume")),
("sessionId", Json::string(session_id)),
]),
)
Clear(session_id~) =>
Json::object(
Map::from_array([
("action", Json::string("clear")),
("sessionId", Json::string(session_id)),
]),
)
}
}
///|
pub fn LodyGoalControlRequest::from_json(
raw : Json,
) -> Result[LodyGoalControlRequest, String] {
try {
let ctx = "lody.goalControl"
let fields = object_fields(raw, ctx)
match req_string(fields, ctx, "action") {
"set" =>
Ok(
Set(
session_id=req_string(fields, ctx, "sessionId"),
objective=req_string(fields, ctx, "objective"),
),
)
"pause" => Ok(Pause(session_id=req_string(fields, ctx, "sessionId")))
"resume" => Ok(Resume(session_id=req_string(fields, ctx, "sessionId")))
"clear" => Ok(Clear(session_id=req_string(fields, ctx, "sessionId")))
action =>
raise DecodeError::Msg(
"\{ctx}: field \"action\": unknown lody goal action: \"\{action}\"",
)
}
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodyGoalControlResponse` — `_lody/session/goal` result; `goal` is a
/// required key that is nullable upstream: `null` when no goal is currently
/// set (a missing key is a decode error).
pub(all) struct LodyGoalControlResponse {
goal : LodyGoalSnapshot?
} derive(Eq, Debug)
///|
pub fn LodyGoalControlResponse::to_json(self : LodyGoalControlResponse) -> Json {
match self.goal {
Some(goal) => Json::object(Map::from_array([("goal", goal.to_json())]))
None => Json::object(Map::from_array([("goal", Json::null())]))
}
}
///|
pub fn LodyGoalControlResponse::from_json(
raw : Json,
) -> Result[LodyGoalControlResponse, String] {
try {
let ctx = "lody.goalControlResponse"
let fields = object_fields(raw, ctx)
Ok(LodyGoalControlResponse::{
goal: req_sub_nullable(fields, ctx, "goal", LodyGoalSnapshot::from_json),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySessionHistoryReadRequest` — `_lody/session/history/read` params.
pub(all) struct LodySessionHistoryReadRequest {
session_id : String
} derive(Eq, Debug)
///|
pub fn LodySessionHistoryReadRequest::to_json(
self : LodySessionHistoryReadRequest,
) -> Json {
Json::object(Map::from_array([("sessionId", Json::string(self.session_id))]))
}
///|
pub fn LodySessionHistoryReadRequest::from_json(
raw : Json,
) -> Result[LodySessionHistoryReadRequest, String] {
try {
let ctx = "lody.historyRead.request"
let fields = object_fields(raw, ctx)
Ok(LodySessionHistoryReadRequest::{
session_id: req_string(fields, ctx, "sessionId"),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySessionHistoryReadResponse` — an empty object upstream. How the
/// actual history content is carried is missing from the contract (likely a
/// placeholder) — awaiting on-wire verification. Decoding tolerates and
/// ignores any extra fields.
pub(all) struct LodySessionHistoryReadResponse {} derive(Eq, Debug)
///|
pub fn LodySessionHistoryReadResponse::to_json(
_self : LodySessionHistoryReadResponse,
) -> Json {
Json::object(Map::from_array([]))
}
///|
pub fn LodySessionHistoryReadResponse::from_json(
raw : Json,
) -> Result[LodySessionHistoryReadResponse, String] {
try {
let _ = object_fields(raw, "lody.historyRead.response")
Ok(LodySessionHistoryReadResponse::{ })
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySubagentsListRequest` — `_lody/subagents/list` params.
pub(all) struct LodySubagentsListRequest {
session_id : String
active_only : Bool?
} derive(Eq, Debug)
///|
pub fn LodySubagentsListRequest::to_json(
self : LodySubagentsListRequest,
) -> Json {
let pairs : Array[(String, Json)] = [
("sessionId", Json::string(self.session_id)),
]
match self.active_only {
Some(v) => pairs.push(("activeOnly", Json::boolean(v)))
None => ()
}
Json::object(Map::from_array(pairs))
}
///|
pub fn LodySubagentsListRequest::from_json(
raw : Json,
) -> Result[LodySubagentsListRequest, String] {
try {
let ctx = "lody.subagents.list.request"
let fields = object_fields(raw, ctx)
Ok(LodySubagentsListRequest::{
session_id: req_string(fields, ctx, "sessionId"),
active_only: opt_bool(fields, ctx, "activeOnly"),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySubagentsListResponse` — `_lody/subagents/list` result.
pub(all) struct LodySubagentsListResponse {
tasks : Array[LodySubagentTask]
} derive(Eq, Debug)
///|
pub fn LodySubagentsListResponse::to_json(
self : LodySubagentsListResponse,
) -> Json {
Json::object(
Map::from_array([
("tasks", Json::array(self.tasks.map(fn(task) { task.to_json() }))),
]),
)
}
///|
pub fn LodySubagentsListResponse::from_json(
raw : Json,
) -> Result[LodySubagentsListResponse, String] {
try {
let ctx = "lody.subagents.list.response"
let fields = object_fields(raw, ctx)
let tasks : Array[LodySubagentTask] = req_array(fields, ctx, "tasks").map(item => {
match LodySubagentTask::from_json(item) {
Ok(task) => task
Err(message) => raise DecodeError::Msg(message)
}
})
Ok(LodySubagentsListResponse::{ tasks, })
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySubagentCancelRequest` — `_lody/subagents/cancel` params.
pub(all) struct LodySubagentCancelRequest {
session_id : String
task_id : String
reason : String?
} derive(Eq, Debug)
///|
pub fn LodySubagentCancelRequest::to_json(
self : LodySubagentCancelRequest,
) -> Json {
let pairs : Array[(String, Json)] = [
("sessionId", Json::string(self.session_id)),
("taskId", Json::string(self.task_id)),
]
match self.reason {
Some(v) => pairs.push(("reason", Json::string(v)))
None => ()
}
Json::object(Map::from_array(pairs))
}
///|
pub fn LodySubagentCancelRequest::from_json(
raw : Json,
) -> Result[LodySubagentCancelRequest, String] {
try {
let ctx = "lody.subagents.cancel.request"
let fields = object_fields(raw, ctx)
Ok(LodySubagentCancelRequest::{
session_id: req_string(fields, ctx, "sessionId"),
task_id: req_string(fields, ctx, "taskId"),
reason: opt_string(fields, ctx, "reason"),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySubagentCancelResponse` — an empty object upstream. Decoding
/// tolerates and ignores any extra fields.
pub(all) struct LodySubagentCancelResponse {} derive(Eq, Debug)
///|
pub fn LodySubagentCancelResponse::to_json(
_self : LodySubagentCancelResponse,
) -> Json {
Json::object(Map::from_array([]))
}
///|
pub fn LodySubagentCancelResponse::from_json(
raw : Json,
) -> Result[LodySubagentCancelResponse, String] {
try {
let _ = object_fields(raw, "lody.subagents.cancel.response")
Ok(LodySubagentCancelResponse::{ })
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySubagentOutputRequest` — `_lody/subagents/output` params.
pub(all) struct LodySubagentOutputRequest {
session_id : String
task_id : String
tail : Int?
} derive(Eq, Debug)
///|
pub fn LodySubagentOutputRequest::to_json(
self : LodySubagentOutputRequest,
) -> Json {
let pairs : Array[(String, Json)] = [
("sessionId", Json::string(self.session_id)),
("taskId", Json::string(self.task_id)),
]
match self.tail {
Some(v) => pairs.push(("tail", Json::number(v.to_double())))
None => ()
}
Json::object(Map::from_array(pairs))
}
///|
pub fn LodySubagentOutputRequest::from_json(
raw : Json,
) -> Result[LodySubagentOutputRequest, String] {
try {
let ctx = "lody.subagents.output.request"
let fields = object_fields(raw, ctx)
Ok(LodySubagentOutputRequest::{
session_id: req_string(fields, ctx, "sessionId"),
task_id: req_string(fields, ctx, "taskId"),
tail: opt_int(fields, ctx, "tail"),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}
///|
/// `LodySubagentOutputResponse` — `_lody/subagents/output` result.
pub(all) struct LodySubagentOutputResponse {
output : String
} derive(Eq, Debug)
///|
pub fn LodySubagentOutputResponse::to_json(
self : LodySubagentOutputResponse,
) -> Json {
Json::object(Map::from_array([("output", Json::string(self.output))]))
}
///|
pub fn LodySubagentOutputResponse::from_json(
raw : Json,
) -> Result[LodySubagentOutputResponse, String] {
try {
let ctx = "lody.subagents.output.response"
let fields = object_fields(raw, ctx)
Ok(LodySubagentOutputResponse::{
output: req_string(fields, ctx, "output"),
})
} catch {
DecodeError::Msg(message) => Err(message)
}
}