blob: c00f4617316166b98c8d5327aefa7de8adcc95bb [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use maka_agent_facts::execution::DirectoryIdentity;
use maka_agent_facts::execution::WorkspaceIdentity;
use maka_agent_facts::history::RowPosition;
use maka_agent_ports::session::history::Cursor;
use maka_agent_ports::session::history::Role;
use maka_plugin_core::contract::{Contract, Interface, Method, MethodMode, Transport};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::BTreeMap;
#[path = "contract_context.rs"]
mod context;
pub use context::*;
#[path = "contract_files.rs"]
mod files;
pub use files::*;
#[path = "contract_fork.rs"]
mod fork;
pub use fork::*;
#[path = "contract_git.rs"]
mod git;
pub use git::*;
#[path = "contract_goal.rs"]
mod goal;
#[path = "contract_imports.rs"]
mod imports;
#[path = "contract_plan.rs"]
mod plan;
pub use goal::*;
pub use maka_agent_facts::execution::CollaborationMode;
pub use plan::*;
#[path = "contract_todo.rs"]
mod todo;
pub use todo::*;
#[path = "contract_recap.rs"]
mod recap;
pub use recap::*;
#[path = "contract_scheduler.rs"]
mod scheduler;
pub use scheduler::*;
#[path = "contract_recall.rs"]
mod recall;
pub use imports::*;
pub use recall::*;
#[path = "contract_projects.rs"]
mod projects;
pub use projects::*;
#[path = "contract_execution.rs"]
mod execution;
pub use execution::*;
#[path = "contract_compaction.rs"]
mod compaction;
pub use compaction::*;
#[path = "contract_interactions.rs"]
mod interaction;
pub use interaction::*;
#[path = "contract_permissions.rs"]
mod permissions;
pub use maka_agent_facts::configuration::ModelSelection;
pub use permissions::*;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentConfiguration")]
pub struct Configuration {
/// Deployment locale fallback; saved Root preference takes precedence.
#[serde(default)]
pub locale: String,
/// Defer optional tool schemas until the model discovers them. This affects
/// presentation only; every call still uses its current authorized binding.
#[serde(default)]
pub tool_discovery: bool,
/// Permit creation of Host-owned Git worktrees from published directories.
#[serde(default)]
pub isolated_workspaces: bool,
/// Select Maka's assistant policy and workspace guidance explicitly.
#[serde(default)]
pub assistant: Option<AssistantConfiguration>,
/// Enable model proposals and approved scheduled work for this Agent.
#[serde(default)]
pub scheduled_tasks: bool,
/// Enable explicitly approved, bounded Goal continuation.
#[serde(default)]
pub goals: bool,
/// Enable planning, reviewed approval and execution progress.
#[serde(default)]
pub plans: bool,
/// Enable the session-scoped, model-maintained checklist.
#[serde(default)]
pub todo: bool,
/// Generate a bounded auxiliary title for automatically named conversations.
#[serde(default)]
pub automatic_titles: bool,
/// Enable explicit, bounded session recap requests and cached reads.
#[serde(default)]
pub recaps: bool,
/// Explicit access to this Agent’s earlier conversations for model tools.
#[serde(default)]
pub recall: bool,
/// Explicit service backends; discovery does not authorize execution.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub executors: Vec<crate::executor::ServiceExecutor>,
/// Explicit Library import for immutable skill input preparation and metadata.
/// This does not select model tools or confer a service grant.
#[serde(default)]
#[schemars(length(min = 1))]
pub skill_library: Option<String>,
/// Initial policy within the selected workspace capability.
pub permissions: WorkspacePermissions,
/// Installation-published directories, captured without creating workspace markers.
pub workspace_roots: Vec<maka_host_runtime::DirectoryRootSpec>,
/// Explicit read-only roots for user-selected conversation sources.
#[serde(default)]
pub import_roots: Vec<maka_host_runtime::DirectoryRootSpec>,
/// Explicitly selected, frozen application service tools, alongside configured native tools.
pub tools: Vec<ServiceTool>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentAssistantConfiguration")]
pub struct AssistantConfiguration {
/// Select this home for global instructions and explicit AGENTS.md editing.
#[serde(default)]
#[schemars(length(min = 1))]
pub home: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentServiceTool")]
pub struct ServiceTool {
/// Allow this selected service inside Code Mode. Binding and permission
/// checks are identical to a direct call; omitted keeps direct-only behavior.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub nestable: bool,
/// Explicit input projection. Skill tools receive the actual Agent tool names,
/// outside model-controlled arguments; this is compatibility data, not authority.
#[serde(default)]
pub input: ToolInput,
/// Explicit versioned renderer key, frozen with the call; never inferred from its name.
#[serde(default)]
#[schemars(length(min = 1))]
pub presentation: Option<String>,
/// Display only; the selected name, contract and binding still identify execution.
#[serde(default)]
pub title: Option<maka_agent_facts::display::Text>,
/// Explicit model projection; JSON data never implicitly grants image access.
pub result: ToolResult,
/// Additional user consent for this exact call; service grants remain independent.
pub confirmation: ToolConfirmation,
#[schemars(length(min = 1))]
pub name: String,
#[schemars(length(min = 1))]
pub description: String,
#[schemars(length(min = 1))]
pub import: String,
#[schemars(length(min = 1))]
pub method: String,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentToolInput")]
pub enum ToolInput {
#[default]
Json,
Skill,
Web,
/// Display-only command title; recorded in history, not forwarded to the process service.
Shell,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentToolResult")]
pub enum ToolResult {
Json,
Image,
/// Session-owned Computer REPL output, retained with its original receipt.
Computer,
}
/// Bounded image bytes from a selected subscription. Complete is a producer
/// return value, never an emitted item or an executor-cleanup acknowledgement.
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentToolImageFrame")]
pub enum ImageFrame {
Chunk {
#[schemars(regex(pattern = "^image/(png|jpeg|gif|webp)$"))]
mime_type: String,
#[schemars(range(min = 1, max = 9_007_199_254_740_991u64))]
total_bytes: usize,
#[schemars(range(max = 9_007_199_254_740_991u64))]
offset: usize,
#[schemars(length(min = 1, max = 43692))]
data: String,
},
Complete,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentToolConfirmation")]
pub enum ToolConfirmation {
Required,
Preapproved,
}
pub fn configuration_schema() -> Value {
serde_json::to_value(schemars::schema_for!(Configuration)).expect("configuration schema")
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentList")]
pub struct List {
pub filter: SessionFilter,
pub position: SessionPosition,
#[serde(default)]
pub scope: SessionListScope,
/// Literal, case-sensitive title substring; an empty query matches all titles.
#[serde(default)]
pub title_query: String,
}
#[derive(Clone, Default, Deserialize, Serialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentSessionListScope")]
pub enum SessionListScope {
#[default]
All,
Project {
project_id: uuid::Uuid,
},
/// Resolve the exact workspace from an owned session, never a caller path.
Workspace {
#[schemars(length(min = 1))]
session_id: String,
},
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentSessionFilter")]
pub enum SessionFilter {
All,
Archived,
NeedsYou,
}
#[derive(Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentSessionPosition")]
pub enum SessionPosition {
Start,
At {
#[schemars(length(min = 1))]
cursor: String,
},
After {
revision: String,
#[schemars(length(min = 1))]
cursor: String,
},
Before {
revision: String,
#[schemars(length(min = 1))]
cursor: String,
},
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentCreate")]
pub struct Create {
/// Treat title as a placeholder for one title derived from the first user message.
#[serde(default)]
pub automatic_title: bool,
/// Immutable narrowing of this Agent's installed tools. None uses the installation;
/// an empty list permits no model tools. External executors cannot enforce this.
#[serde(default)]
#[schemars(extend("uniqueItems" = true))]
pub tools: Option<Vec<String>>,
#[schemars(length(min = 1))]
pub title: String,
pub labels: Vec<String>,
pub workspace: WorkspaceSelection,
}
#[derive(Clone, Deserialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentWorkspaceSelection")]
pub enum WorkspaceSelection {
IsolatedGit {
selection: DirectorySelection,
},
Project {
project: ProjectRef,
selection: DirectorySelection,
},
Directory {
selection: DirectorySelection,
},
Session {
#[schemars(length(min = 1))]
session_id: String,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDirectorySelection")]
pub struct DirectorySelection {
#[schemars(length(min = 1))]
pub root_id: String,
pub segments: Vec<String>,
#[schemars(with = "String", regex(pattern = "^sha256:[a-f0-9]{64}$"))]
pub directory_identity: DirectoryIdentity,
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentDirectories")]
pub enum Directories {
Roots,
Children {
selection: DirectorySelection,
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<String>")]
after: Option<String>,
},
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDirectory")]
pub struct Directory {
pub name: String,
pub path: String,
pub selection: DirectorySelection,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentDirectoryPage")]
pub enum DirectoryPage {
Roots {
roots: Vec<Directory>,
},
Children {
directory: Directory,
#[schemars(length(max = 32))]
children: Vec<Directory>,
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<String>")]
after: Option<String>,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentWorkspace")]
pub struct Workspace {
/// Native owner allocation; never accepted from a caller as workspace authority.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub worktree: Option<Box<maka_fs_tools::worktree::Binding>>,
/// Optional membership in this Agent's canonical Project catalog.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub project_id: Option<uuid::Uuid>,
#[schemars(length(min = 1))]
pub path: String,
#[schemars(with = "String", regex(pattern = "^sha256:[a-f0-9]{64}$"))]
pub directory_identity: DirectoryIdentity,
#[schemars(with = "String", regex(pattern = "^workspace:v1:[A-Fa-f0-9-]{36}$"))]
pub identity: WorkspaceIdentity,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentMetadata")]
pub struct Metadata {
/// Changing collaboration is only allowed while the Session is idle.
#[serde(default)]
pub collaboration_mode: Option<CollaborationMode>,
/// Omission leaves the permission boundary and its approvals unchanged.
#[serde(default)]
pub permissions: Option<PermissionChange>,
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(min = 1, max = 9_007_199_254_740_991u64))]
pub expected_revision: u64,
#[schemars(length(min = 1))]
pub title: String,
pub labels: Vec<String>,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentChangeSession")]
pub struct ChangeSession {
pub session_id: String,
pub expected_revision: u64,
pub action: SessionAction,
}
#[derive(Clone, Copy, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentSessionAction")]
pub enum SessionAction {
Archive,
Restore,
Remove,
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentSessionChanged")]
pub enum SessionChanged {
Changed {
session: Box<Session>,
},
Removed {
#[serde(rename = "sessionId")]
session_id: String,
},
RevisionConflict {
expected: u64,
actual: u64,
},
Rejected {
reason: Rejection,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentGlobalInstructionSource")]
pub enum GlobalInstructionSource {
Maka,
Agents,
}
#[derive(Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentGlobalInstructionsView")]
pub enum GlobalInstructionsView {
Available {
source: GlobalInstructionSource,
path: String,
revision: String,
content: String,
exists: bool,
},
Unavailable,
}
#[derive(Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(rename = "AgentGlobalInstructionsRead")]
pub struct GlobalInstructionsRead {}
#[derive(Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(rename = "AgentGlobalInstructionsUpdate")]
pub struct GlobalInstructionsUpdate {
pub source: GlobalInstructionSource,
pub revision: String,
pub content: String,
}
#[derive(Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentGlobalInstructionsUpdated")]
pub enum GlobalInstructionsUpdated {
Saved,
Changed,
Unavailable,
}
/// Read-only suggestions resolved against the session's actual skill context.
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentSkillCandidatesRead")]
pub struct SkillCandidatesRead {
pub session_id: String,
pub backend: SkillCandidatesBackend,
pub query: String,
}
#[derive(Deserialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentSkillCandidatesBackend")]
pub enum SkillCandidatesBackend {
Model {
model: ModelSelection,
thinking_level: Option<maka_agent_facts::execution::ThinkingLevel>,
},
Executor {
selection: crate::executor::Selection,
},
}
#[derive(Serialize, JsonSchema, Default)]
#[serde(rename_all = "camelCase")]
#[schemars(rename = "AgentSkillCandidates")]
pub struct SkillCandidates {
pub revision: Option<String>,
pub skills: Vec<SkillCandidate>,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AgentSkillCandidate")]
pub struct SkillCandidate {
pub reference: String,
pub name: String,
pub description: String,
pub invocation: String,
}
/// The next turn's choice, independent of an already admitted execution.
/// Model revisions are resolved afresh; preferences never grant execution authority.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentBackendPreference")]
pub enum BackendPreference {
Model {
#[schemars(length(min = 1))]
connection_id: String,
#[schemars(length(min = 1))]
model_id: String,
thinking_level: Option<maka_agent_facts::execution::ThinkingLevel>,
},
Executor {
selection: crate::executor::Selection,
},
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentSelectBackend")]
pub struct SelectBackend {
pub session_id: String,
pub backend: BackendPreference,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentRejection")]
pub enum Rejection {
TitleInvalid,
LabelsInvalid,
ToolsUnavailable,
Busy,
WorkspaceUnavailable,
SessionUnavailable,
HistoryUnavailable,
ManagedSession,
Closed,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentCreated")]
pub enum Created {
Created { session: Box<Session> },
Rejected { reason: Rejection },
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentMetadataResult")]
pub enum MetadataResult {
Committed { session: Box<Session> },
RevisionConflict { expected: u64, actual: u64 },
Rejected { reason: Rejection },
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentSend")]
pub struct Send {
/// IDs of immutable user uploads in this Session; metadata is resolved by the owner.
#[serde(default)]
pub attachments: Vec<String>,
pub model: ModelSelection,
/// Omission/null uses the configured model default; `off` is explicit.
pub thinking_level: Option<maka_agent_facts::execution::ThinkingLevel>,
#[schemars(length(min = 1))]
pub session_id: String,
pub message: String,
}
#[derive(Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(rename = "AgentExecutorsRead")]
pub struct ExecutorsRead {}
#[derive(Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(rename = "AgentExecutors")]
pub struct Executors {
pub executors: Vec<String>,
pub setup: Vec<String>,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentExecute")]
pub struct Execute {
/// IDs of immutable user uploads in this Session, resolved by the Agent owner.
#[serde(default)]
pub attachments: Vec<String>,
#[schemars(length(min = 1))]
pub session_id: String,
pub message: String,
pub executor: crate::executor::Selection,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentUploadAttachment")]
pub struct UploadAttachment {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(length(min = 1))]
pub name: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub bytes: usize,
#[schemars(regex(pattern = "^sha256:[a-f0-9]{64}$"))]
pub digest: String,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentAttachmentUploadResult")]
pub enum AttachmentUploadResult {
Uploaded { attachment: Attachment },
Rejected { reason: AttachmentRejection },
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentAttachmentRejection")]
pub enum AttachmentRejection {
InvalidFile,
Closed,
Archived,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentAttachment")]
pub struct Attachment {
pub session_id: String,
pub id: String,
pub name: String,
pub mime_type: String,
pub bytes: u64,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentMarkRead")]
pub struct MarkRead {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(length(min = 1))]
pub message_id: String,
}
#[derive(Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentMarkReadResult")]
pub enum MarkReadResult {
Observed { session: Box<Session> },
Rejected { reason: Rejection },
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentStop")]
pub struct Stop {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(length(min = 1))]
pub invocation_id: String,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentWatch")]
pub struct Watch {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub after: u64,
}
/// Stable business-data origin, independent of package or activation revisions.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDataSource")]
pub struct DataSource {
pub state_domain: String,
pub deployment: uuid::Uuid,
pub namespace: maka_plugin_core::composition::InstanceId,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentSession")]
pub struct Session {
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<SessionBranch>")]
pub branch: Option<SessionBranch>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub backend: Option<BackendPreference>,
#[serde(default)]
pub collaboration_mode: CollaborationMode,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<String>>,
pub data_source: Box<DataSource>,
pub permissions: WorkspacePermissions,
pub boundary_revision: u64,
pub id: String,
pub title: String,
pub labels: Vec<String>,
pub workspace: Workspace,
pub revision: u64,
pub updated_at: u64,
pub archived: bool,
pub has_unread: bool,
pub activity: SessionActivity,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentSessionActivity")]
pub enum SessionActivity {
Idle,
Working,
Waiting,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentSessionPage")]
pub struct SessionPage {
pub revision: String,
pub needs_you_count: u64,
#[schemars(length(max = 32))]
pub sessions: Vec<Session>,
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<String>")]
pub before: Option<String>,
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<String>")]
pub after: Option<String>,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentSendResult")]
pub enum SendResult {
Rejected {
session_id: String,
reason: SkillInputRejection,
skills: Option<maka_skills::SkillInvocationResult>,
},
Started {
session_id: String,
invocation_id: String,
message_id: String,
},
Queued {
session_id: String,
message_id: String,
revision: u64,
},
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentSkillInputRejection")]
pub enum SkillInputRejection {
SkillsUnavailable,
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentStopped")]
pub struct Stopped {
pub requested: bool,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDelivery")]
pub struct Delivery {
pub sequence: u64,
pub invocation_id: String,
pub turn_id: String,
pub fact: DeliveryFact,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentDeliveryFact")]
pub enum DeliveryFact {
Opened,
/// Both external text streams share the original ExecutorStarted message.
ExecutorStarted {
message_id: String,
},
/// Canonical transcript facts changed; clients query bounded history.
TranscriptChanged,
StepEnded {
step_id: String,
/// The model/executor completed; this says nothing about tool business success.
completed: bool,
},
PartStarted {
message_id: String,
step_id: String,
part_id: String,
text_kind: ContentKind,
},
Delta {
step_id: String,
part_id: String,
text: String,
},
PartFinished {
step_id: String,
part_id: String,
},
/// Model input observations are display-only; they cannot authorize a tool effect.
ToolInputStarted {
tool_use_id: String,
step_id: String,
name: String,
provider_executed: bool,
},
ToolInputDelta {
tool_use_id: String,
text: String,
},
/// Complete model input was observed, not authorization to execute it.
ToolInputReady {
tool_use_id: String,
step_id: String,
name: String,
provider_executed: bool,
},
/// Original Host admission, not a claim that the effect is currently using CPU.
ToolDispatched {
tool_use_id: String,
name: String,
title: Option<maka_agent_facts::display::Text>,
},
ToolRejected {
tool_use_id: String,
},
ToolSettled {
tool_use_id: String,
settlement: maka_agent_facts::tool_call::ToolSettlement,
},
/// Provider-reported completion, distinct from a Host effect settlement.
ProviderToolResult {
tool_use_id: String,
is_error: bool,
},
ExecutorToolStart {
tool_use_id: String,
name: String,
},
ExecutorToolProgress {
tool_use_id: String,
/// The most recent at most 2048 codepoints of reported progress, not the complete result.
text: String,
},
ExecutorToolResult {
tool_use_id: String,
is_error: bool,
},
Ended {
failed: bool,
},
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentContentKind")]
pub enum ContentKind {
Text,
Thinking,
}
impl From<maka_agent_facts::model::TextKind> for ContentKind {
fn from(value: maka_agent_facts::model::TextKind) -> Self {
match value {
maka_agent_facts::model::TextKind::Text => Self::Text,
maka_agent_facts::model::TextKind::Thinking => Self::Thinking,
}
}
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentSessionRead")]
pub struct SessionRead {
#[schemars(length(min = 1))]
pub session_id: String,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDiagnostics")]
pub struct Diagnostics {
#[schemars(length(min = 1))]
pub session_id: String,
pub position: DiagnosticPosition,
}
#[derive(Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentDiagnosticPosition")]
pub enum DiagnosticPosition {
Latest,
Before {
#[schemars(range(max = 9_007_199_254_740_991u64))]
through: u64,
#[schemars(range(min = 1, max = 9_007_199_254_740_991u64))]
sequence: u64,
},
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDiagnostic")]
pub struct Diagnostic {
pub sequence: u64,
pub event_id: String,
pub recorded_at: f64,
pub detail: maka_agent_facts::diagnostics::DiagnosticDetail,
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDiagnosticPage")]
pub struct DiagnosticPage {
pub through: u64,
pub entries: Vec<Diagnostic>,
pub next_before: Option<u64>,
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentDiagnosticChange")]
pub struct DiagnosticChange {
/// Latest diagnostic event sequence, independently of transcript progress.
pub revision: u64,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentObservation")]
pub struct Observation {
pub session: Session,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub compacting: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub remembered_backend: Option<BackendPreference>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metrics: Option<SessionMetrics>,
pub through: u64,
pub run: Option<Run>,
pub parts: Vec<Part>,
/// Replay starts for active tool display, read at the same fence as the run.
pub tool_seeds: Vec<ToolSeed>,
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentToolSeed")]
pub struct ToolSeed {
pub tool_use_id: String,
pub start_sequence: u64,
}
/// Display-only readings from the latest completed main-model request.
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentSessionMetrics")]
pub struct SessionMetrics {
pub model_id: String,
pub connection_id: Option<String>,
pub context_tokens: Option<u64>,
pub context_window: Option<u64>,
pub approximate: bool,
/// The context count is the last completed request's baseline; newer additions are unknown.
pub context_last_known: bool,
/// Provider output tokens divided by the model request's wall time.
/// Includes reasoning and time to first token; excludes tool/user waits.
pub output_tokens_per_second: Option<f64>,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentRun")]
pub struct Run {
pub invocation_id: String,
pub turn_id: String,
pub state: RunState,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentRunState")]
pub enum RunState {
Admitted,
Running,
WaitingForUser,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentPart")]
pub struct Part {
pub start_sequence: u64,
pub message_id: String,
pub step_id: String,
pub part_id: String,
pub text_kind: ContentKind,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentDeliveryPage")]
pub enum DeliveryPage {
Events {
through: u64,
next_after: u64,
events: Vec<Delivery>,
},
Queue {
queue: Queue,
},
Interactions {
pending: PendingInteractions,
},
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentQueue")]
pub struct Queue {
pub revision: u64,
pub entries: Vec<QueueEntry>,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentQueueEntry")]
pub struct QueueEntry {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub origin: Option<maka_agent_facts::message::MessageOrigin>,
pub message_id: String,
pub kind: QueueKind,
#[schemars(length(max = 80))]
pub preview: String,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentQueueKind")]
pub enum QueueKind {
InFlight,
Steering,
Followup,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentQueueMessage")]
pub struct QueueMessage {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(length(min = 1))]
pub message_id: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub expected_revision: u64,
}
#[derive(Serialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentQueueMessageResult")]
pub enum QueueMessageResult {
Ready {
revision: u64,
has_attachments: bool,
message: String,
},
RevisionConflict {
expected: u64,
actual: u64,
},
Missing,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentQueueMutation")]
pub struct QueueMutation {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub expected_revision: u64,
pub edit: QueueAction,
}
#[derive(Deserialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentQueueAction")]
pub enum QueueAction {
Retract {
#[schemars(length(min = 1))]
message_id: String,
},
Promote {
#[schemars(length(min = 1))]
message_id: String,
},
Update {
#[schemars(length(min = 1))]
message_id: String,
message: String,
},
Reorder {
#[schemars(length(min = 1))]
message_ids: Vec<String>,
},
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentQueueMutationResult")]
pub enum QueueMutationResult {
Committed { revision: u64 },
RevisionConflict { expected: u64, actual: u64 },
Rejected { reason: QueueRejection },
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[schemars(rename = "AgentQueueRejection")]
pub enum QueueRejection {
Closed,
Missing,
InFlight,
InvalidEdit,
ExecutionChanged,
NotRunning,
}
#[derive(Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryAttachment")]
pub struct HistoryAttachment {
pub name: String,
pub mime_type: String,
pub bytes: u64,
pub kind: maka_agent_facts::attachment::AttachmentKind,
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryChunk")]
pub struct HistoryChunk {
/// Part of the successfully completed native Turn's final output at `through`.
/// Includes all body parts and source citations; never a Thinking field.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub final_output: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<maka_agent_ports::session::history::HistoryModel>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub origin: Option<maka_agent_facts::message::MessageOrigin>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub compaction: Option<maka_agent_ports::session::history::Compaction>,
/// Display metadata only, on the first user-message fragment; no storage capability.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attachments: Vec<HistoryAttachment>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timing: Option<maka_agent_ports::session::history::TurnTiming>,
pub field: maka_agent_ports::session::history::HistoryField,
pub message_id: String,
pub turn_id: String,
pub timestamp: u64,
pub role: Role,
pub position: RowPosition,
pub offset: u64,
pub total_bytes: u64,
pub text: String,
#[schemars(
with = "maka_plugin_core::wire_schema::RequiredNullable<maka_agent_ports::session::history::Tool>"
)]
pub tool: Option<maka_agent_ports::session::history::Tool>,
}
#[derive(Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryRead")]
pub struct History {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub through: Option<u64>,
pub position: HistoryPosition,
#[serde(default)]
pub include_thinking: bool,
#[serde(default)]
pub view: maka_agent_ports::session::history::HistoryView,
}
pub use maka_agent_ports::session::history::Position as HistoryPosition;
pub use maka_agent_ports::session::history::Prompt as HistoryPrompt;
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryLandmarksRead")]
pub struct HistoryLandmarksRead {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub through: u64,
}
/// Sampled canonical display positions, not a complete Turn outline or an
/// execution grant.
#[derive(Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryLandmarks")]
pub struct HistoryLandmarks {
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub through: u64,
#[schemars(length(max = 64))]
pub landmarks: Vec<HistoryLandmark>,
}
#[derive(Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryLandmark")]
pub struct HistoryLandmark {
#[schemars(length(min = 1))]
pub turn_id: String,
pub position: RowPosition,
pub last_position: RowPosition,
#[schemars(length(max = 96))]
pub label: String,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryPromptRead")]
pub struct HistoryPromptRead {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(min = 1, max = 9_007_199_254_740_991u64))]
pub through: u64,
pub position: RowPosition,
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistorySearch")]
pub struct HistorySearch {
#[schemars(length(min = 1))]
pub session_id: String,
/// Original raw-event fence, shared with history reads.
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub through: u64,
/// Exclusive transcript-row position; null starts a scan.
pub after: Option<RowPosition>,
/// Literal query; no normalization.
#[schemars(length(min = 1))]
pub query: String,
/// False uses Unicode simple case folding, without locale or multi-character folding.
pub case_sensitive: bool,
/// Require no adjacent Unicode word character (Alphabetic, marks, decimal
/// digits, connector punctuation or join controls); not dictionary segmentation.
pub whole_word: bool,
pub include_internal: bool,
}
#[derive(Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistoryMatch")]
pub struct HistoryMatch {
/// Exact canonical field to read through the source query; history body may omit it.
pub field: maka_agent_ports::session::history::SourceField,
/// Exact transcript row. Open with HistoryPosition::Row at the same raw-event
/// fence: Thinking for a thinking match, Body for every other source field.
pub position: RowPosition,
#[schemars(length(max = 384))]
pub preview: String,
}
#[derive(Serialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentHistorySearchPage")]
pub enum HistorySearchPage {
Ready {
through: u64,
#[schemars(length(max = 16))]
matches: Vec<HistoryMatch>,
/// Continue even when this batch has no matches. Null is the end of the scan.
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<RowPosition>")]
next_after: Option<RowPosition>,
},
}
#[derive(Serialize, JsonSchema, Deserialize)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentHistoryPage")]
pub enum HistoryPage {
Ready {
through: u64,
chunks: Vec<HistoryChunk>,
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<Cursor>")]
before: Option<Cursor>,
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<Cursor>")]
after: Option<Cursor>,
},
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentHistorySourceRead")]
pub struct HistorySourceRead {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub through: u64,
pub source: HistorySourceReference,
pub field: maka_agent_ports::session::history::SourceField,
/// Optional JSON keys/array indices within arguments, result or receipt.
#[serde(default)]
pub path: Option<Vec<maka_agent_ports::session::history::SourceSegment>>,
pub position: maka_agent_ports::session::history::SourcePosition,
}
#[derive(Deserialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentHistorySourceReference")]
pub enum HistorySourceReference {
Row {
position: RowPosition,
},
ToolUse {
#[schemars(length(min = 1))]
tool_use_id: String,
},
}
#[derive(Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
#[schemars(rename = "AgentHistorySourcePage")]
pub enum HistorySourcePage {
Ready {
through: u64,
source: Box<maka_agent_ports::session::history::HistorySource>,
/// Complete file-path evidence resolved on the Host for copying only.
/// This is display text, never a filesystem capability or open command.
#[serde(rename = "filePath", skip_serializing_if = "Option::is_none")]
file_path: Option<String>,
},
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentToolImageRead")]
pub struct ToolImageRead {
#[schemars(length(min = 1))]
pub session_id: String,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub through: u64,
pub position: RowPosition,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub offset: u64,
}
#[derive(Serialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentToolImagePage")]
pub enum ToolImagePage {
Ready {
through: u64,
position: RowPosition,
offset: u64,
#[schemars(range(min = 1, max = 9_007_199_254_740_991u64))]
total_bytes: u64,
#[schemars(regex(pattern = "^image/(png|jpeg|gif|webp|avif)$"))]
mime_type: String,
#[schemars(regex(pattern = "^sha256:[a-f0-9]{64}$"))]
digest: String,
/// Standard padded Base64 of at most 32KiB of encoded image bytes.
#[schemars(
length(max = 43692),
regex(pattern = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
)]
data: String,
},
}
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentAttachmentImageRead")]
pub struct AttachmentImageRead {
#[schemars(length(min = 1))]
pub session_id: String,
pub source: AttachmentImageSource,
#[schemars(range(max = 9_007_199_254_740_991u64))]
pub offset: u64,
}
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentAttachmentImageSource")]
pub enum AttachmentImageSource {
Uploaded {
#[schemars(length(min = 1))]
id: String,
},
History {
#[schemars(range(max = 9_007_199_254_740_991u64))]
through: u64,
position: RowPosition,
attachment_index: u32,
},
}
#[derive(Serialize, JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
#[schemars(rename = "AgentAttachmentImagePage")]
pub enum AttachmentImagePage {
Ready {
source: AttachmentImageSource,
offset: u64,
#[schemars(range(min = 1, max = 9_007_199_254_740_991u64))]
total_bytes: u64,
#[schemars(regex(pattern = "^image/(png|jpeg|gif|webp|avif)$"))]
mime_type: String,
#[schemars(regex(pattern = "^sha256:[a-f0-9]{64}$"))]
digest: String,
/// Standard padded Base64 of at most 32KiB of encoded image bytes.
#[schemars(
length(max = 43692),
regex(pattern = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
)]
data: String,
},
}
#[derive(Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(rename = "AgentToolNames")]
pub struct ToolNames {
pub names: Vec<String>,
}
pub fn contract() -> Contract {
fn method<I: JsonSchema, O: JsonSchema>(mode: MethodMode) -> Method {
Method {
progress: None,
mode,
input: serde_json::to_value(schemars::schema_for!(I))
.expect("input schema")
.into(),
output: serde_json::to_value(schemars::schema_for!(O))
.expect("output schema")
.into(),
resources: BTreeMap::new(),
}
}
Contract {
name: "maka.agent.Agent".into(),
version: 1,
transport: Transport::Remote,
interface: Interface::Service {
methods: BTreeMap::from([
(
"globalInstructions".into(),
method::<GlobalInstructionsRead, GlobalInstructionsView>(MethodMode::Query),
),
(
"updateGlobalInstructions".into(),
method::<GlobalInstructionsUpdate, GlobalInstructionsUpdated>(
MethodMode::Mutation,
),
),
(
"skillCandidates".into(),
method::<SkillCandidatesRead, SkillCandidates>(MethodMode::Query),
),
(
"tools".into(),
Method {
progress: None,
mode: MethodMode::Query,
input: serde_json::json!({"type":"object","properties":{},"additionalProperties":false}).into(),
output: schemars::schema_for!(ToolNames).into(),
resources: BTreeMap::new(),
},
),
(
"plan".into(),
method::<PlanRead, PlanView>(MethodMode::Query),
),
(
"watchPlan".into(),
method::<PlanRead, PlanView>(MethodMode::Subscription),
),
(
"planHistory".into(),
method::<PlanHistoryRead, PlanHistory>(MethodMode::Query),
),
(
"planReceipt".into(),
method::<PlanReceiptRead, Option<PlanResult>>(MethodMode::Query),
),
(
"changePlan".into(),
method::<PlanChange, PlanResult>(MethodMode::Mutation),
),
(
"goal".into(),
method::<GoalRead, GoalView>(MethodMode::Query),
),
(
"goalReceipt".into(),
method::<GoalReceiptRead, Option<GoalResult>>(MethodMode::Query),
),
(
"watchGoal".into(),
method::<GoalRead, GoalView>(MethodMode::Subscription),
),
(
"changeGoal".into(),
method::<GoalChange, GoalResult>(MethodMode::Mutation),
),
(
"checklist".into(),
method::<ChecklistRead, Checklist>(MethodMode::Query),
),
(
"recap".into(),
method::<RecapRead, Option<RecapReceipt>>(MethodMode::Query),
),
(
"generateRecap".into(),
method::<RecapGenerate, RecapReceipt>(MethodMode::Mutation),
),
(
"watchChecklist".into(),
method::<ChecklistRead, Checklist>(MethodMode::Subscription),
),
(
"schedules".into(),
method::<ScheduleRead, Schedules>(MethodMode::Query),
),
(
"watchSchedules".into(),
method::<ScheduleRead, Schedules>(MethodMode::Subscription),
),
(
"scheduleAlerts".into(),
method::<ScheduleAlertsRead, ScheduleAlerts>(MethodMode::Subscription),
),
(
"schedule".into(),
method::<ScheduleChange, ScheduleResult>(MethodMode::Mutation),
),
(
"list".into(),
method::<List, SessionPage>(MethodMode::Query),
),
(
"catalog".into(),
method::<List, SessionPage>(MethodMode::Subscription),
),
(
"recall".into(),
method::<RecallQuery, RecallPage>(MethodMode::Query),
),
(
"imports".into(),
method::<ImportsRead, ImportsPage>(MethodMode::Query),
),
(
"import".into(),
method::<ImportChange, ImportResult>(MethodMode::Mutation),
),
(
"importDirectories".into(),
method::<Directories, DirectoryPage>(MethodMode::Query),
),
(
"projects".into(),
method::<ProjectsRead, ProjectsPage>(MethodMode::Query),
),
(
"project".into(),
method::<ProjectChange, ProjectResult>(MethodMode::Mutation),
),
(
"directories".into(),
method::<Directories, DirectoryPage>(MethodMode::Query),
),
(
"observe".into(),
method::<SessionRead, Observation>(MethodMode::Query),
),
(
"diagnostics".into(),
method::<Diagnostics, DiagnosticPage>(MethodMode::Query),
),
(
"watchDiagnostics".into(),
method::<SessionRead, DiagnosticChange>(MethodMode::Subscription),
),
(
"history".into(),
method::<History, HistoryPage>(MethodMode::Query),
),
(
"historyLandmarks".into(),
method::<HistoryLandmarksRead, HistoryLandmarks>(MethodMode::Query),
),
(
"historyPrompt".into(),
method::<HistoryPromptRead, Option<HistoryPrompt>>(MethodMode::Query),
),
(
"search".into(),
method::<HistorySearch, HistorySearchPage>(MethodMode::Query),
),
(
"source".into(),
method::<HistorySourceRead, HistorySourcePage>(MethodMode::Query),
),
(
"toolImage".into(),
method::<ToolImageRead, ToolImagePage>(MethodMode::Query),
),
(
"attachmentImage".into(),
method::<AttachmentImageRead, AttachmentImagePage>(MethodMode::Query),
),
(
"create".into(),
method::<Create, Created>(MethodMode::Mutation),
),
(
"fork".into(),
method::<Fork, ForkResult>(MethodMode::Mutation),
),
(
"forkReceipt".into(),
method::<ForkReceipt, ForkReceiptResult>(MethodMode::Query),
),
(
"listFiles".into(),
method::<FileListRead, FilePage>(MethodMode::Query),
),
(
"watchFiles".into(),
method::<FileWatch, FileChange>(MethodMode::Subscription),
),
(
"readFile".into(),
method::<FileRead, Option<FileReadPart>>(MethodMode::Subscription),
),
(
"context".into(),
method::<ContextRead, ContextReport>(MethodMode::Query),
),
(
"gitStatus".into(),
method::<SessionRead, Option<GitStatus>>(MethodMode::Query),
),
(
"gitDiff".into(),
method::<GitDiffRead, Option<GitDiff>>(MethodMode::Query),
),
(
"snapshotPatch".into(),
method::<ExecutionRead, PatchResult>(MethodMode::Mutation),
),
(
"readPatch".into(),
method::<PatchRead, PatchPage>(MethodMode::Query),
),
(
"metadata".into(),
method::<Metadata, MetadataResult>(MethodMode::Mutation),
),
(
"changeSession".into(),
method::<ChangeSession, SessionChanged>(MethodMode::Mutation),
),
(
"selectBackend".into(),
method::<SelectBackend, MetadataResult>(MethodMode::Mutation),
),
// Authorizes the entire bounded run against the immutable selected
// account/model. A started reply is not a terminal business verdict.
(
"send".into(),
method::<Send, SendResult>(MethodMode::Mutation),
),
(
"execute".into(),
method::<Execute, SendResult>(MethodMode::Mutation),
),
(
"executorSetup".into(),
Method {
mode: MethodMode::Mutation,
input: schemars::schema_for!(crate::executor::setup::Input).into(),
output: schemars::schema_for!(crate::executor::setup::Outcome).into(),
progress: Some(
schemars::schema_for!(crate::executor::setup::Progress).into(),
),
resources: BTreeMap::new(),
},
),
(
"executors".into(),
method::<ExecutorsRead, Executors>(MethodMode::Query),
),
(
"uploadAttachment".into(),
Method {
progress: None,
resources: BTreeMap::from([(
"file".into(),
maka_plugin_core::contract::binary_resource_type().required(),
)]),
..method::<UploadAttachment, AttachmentUploadResult>(MethodMode::Mutation)
},
),
(
"execution".into(),
method::<ExecutionRead, ExecutionResult>(MethodMode::Query),
),
("work".into(), method::<WorkRead, Work>(MethodMode::Query)),
(
"compactionPrompt".into(),
method::<SessionRead, CompactionPrompt>(MethodMode::Query),
),
(
"compact".into(),
method::<Compact, CompactResult>(MethodMode::Mutation),
),
(
"resume".into(),
method::<Resume, ResumeResult>(MethodMode::Mutation),
),
("stop".into(), method::<Stop, Stopped>(MethodMode::Mutation)),
(
"markRead".into(),
method::<MarkRead, MarkReadResult>(MethodMode::Mutation),
),
(
"queue".into(),
method::<SessionRead, Queue>(MethodMode::Query),
),
(
"queueMessage".into(),
method::<QueueMessage, QueueMessageResult>(MethodMode::Query),
),
(
"editQueue".into(),
method::<QueueMutation, QueueMutationResult>(MethodMode::Mutation),
),
(
"pendingInteractions".into(),
method::<SessionRead, PendingInteractions>(MethodMode::Query),
),
(
"interaction".into(),
method::<InteractionRead, maka_agent_facts::interaction::InteractionRecord>(
MethodMode::Query,
),
),
(
"respond".into(),
method::<InteractionRespond, InteractionResult>(MethodMode::Mutation),
),
(
"watch".into(),
method::<Watch, DeliveryPage>(MethodMode::Subscription),
),
]),
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn history_window_contract_distinguishes_end_from_missing_boundaries() {
let Interface::Service { methods } = contract().interface else {
panic!("service contract");
};
let validator = jsonschema::validator_for(&methods["history"].output).unwrap();
let mut page = serde_json::to_value(HistoryPage::Ready {
through: 16,
chunks: Vec::new(),
before: None,
after: Some(Cursor {
field: Default::default(),
position: RowPosition {
source_sequence: 16,
item_index: 0,
},
offset: 0,
}),
})
.unwrap();
assert!(validator.is_valid(&page));
page["chunks"] = json!([{
"messageId":"result", "field":"body", "turnId":"turn", "timestamp":1, "role":"tool_result",
"position":{"sourceSequence":1,"itemIndex":0}, "offset":0, "totalBytes":0, "text":"",
"tool":{"toolUseId":"call", "call":null, "result":{"position":{"sourceSequence":1,"itemIndex":0},"isError":true, "image":false,"settlement":null}}
}]);
assert!(validator.is_valid(&page));
let tool = page["chunks"][0]
.as_object_mut()
.unwrap()
.remove("tool")
.unwrap();
assert!(
!validator.is_valid(&page),
"tool facts are explicit, including null"
);
page["chunks"][0]["tool"] = tool;
page["chunks"][0]["tool"]
.as_object_mut()
.unwrap()
.remove("call");
assert!(
!validator.is_valid(&page),
"missing call reference is not an observed absence"
);
page["chunks"][0]["tool"]["call"] = json!(null);
assert!(validator.is_valid(&page));
for field in ["before", "after"] {
let value = page.as_object_mut().unwrap().remove(field).unwrap();
assert!(!validator.is_valid(&page), "missing {field} is not EOF");
page.as_object_mut().unwrap().insert(field.into(), value);
}
page["after"] = json!(null);
assert!(validator.is_valid(&page));
page["next"] = json!(null);
assert!(
!validator.is_valid(&page),
"removed one-way API is rejected"
);
}
}