Skip to main content

supercode_interchange/orchestration/
profile.rs

1//! The home and its profiles (§2.1): the root folder IS the `default`
2//! profile; `profiles/<name>/` are the named ones.
3
4use std::collections::BTreeMap;
5use std::path::PathBuf;
6
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10
11use super::agent::{AgentDecl, Budget, Conversation, Handoff, SessionUsage, Transfer};
12use super::{Access, ChannelConfig, Fire, Job, Obligation, Route, WebhookSubscription, WorkerSpec};
13use crate::ontology::Binding;
14
15/// The persona: `AGENTS.md` at the profile root, content hash first.
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
17pub struct PersonaRef {
18    /// Always `AGENTS.md` in our folder (`SOUL.md` in a Hermes home).
19    pub path: String,
20    /// The text, when loaded.
21    #[serde(default)]
22    pub text: Option<String>,
23    /// Hex sha256 of the text.
24    pub sha256: String,
25}
26
27/// What a profile carries that the model does not interpret.
28#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
29pub struct ProfileResidue {
30    /// `config.yaml` keys that are the source harness's, verbatim.
31    #[serde(default)]
32    pub config: BTreeMap<String, Value>,
33    /// Unmodeled files, by path relative to the profile dir; copied verbatim.
34    #[serde(default)]
35    pub files: Vec<String>,
36}
37
38/// One profile: a folder with `AGENTS.md` at its root.
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
40pub struct Profile {
41    /// `default` for the root, else the folder name.
42    pub name: String,
43    /// The folder.
44    pub dir: PathBuf,
45    /// O — which harness runs it.
46    #[serde(default)]
47    pub worker: Option<WorkerSpec>,
48    /// O — `AGENTS.md`.
49    #[serde(default)]
50    pub persona: Option<PersonaRef>,
51    /// H — `config.yaml` `platforms:` blocks.
52    #[serde(default)]
53    pub channels: BTreeMap<String, ChannelConfig>,
54    /// H — `gateway.profile_routes`.
55    #[serde(default)]
56    pub routes: Vec<Route>,
57    /// H — `cron/jobs.json`.
58    #[serde(default)]
59    pub jobs: BTreeMap<String, Job>,
60    /// H — `webhook_subscriptions.json`.
61    #[serde(default)]
62    pub subscriptions: BTreeMap<String, WebhookSubscription>,
63    /// H — allowlists and pairing.
64    #[serde(default)]
65    pub access: Access,
66    /// O — the conversations, keyed by their slot (the surface key string for
67    /// a live one, `<key>#<started_at>[#n]` for ended ones).
68    #[serde(default)]
69    pub bindings: BTreeMap<String, Binding>,
70    /// H — `cron/executions.db`.
71    #[serde(default)]
72    pub fires: Vec<Fire>,
73    /// H — `delivery_obligations`.
74    #[serde(default)]
75    pub obligations: Vec<Obligation>,
76    /// O — per-action gates on this profile's agents (G3); they only narrow down the layers.
77    #[serde(default, skip_serializing_if = "Vec::is_empty")]
78    pub budgets: Vec<Budget>,
79    /// What the model does not interpret.
80    #[serde(default)]
81    pub residue: ProfileResidue,
82}
83
84/// The whole home: the persisted half of `OrchestratorState` (§2.1); the
85/// runtime half is never written and is not part of the wire.
86#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
87pub struct Orchestration {
88    /// The home folder.
89    pub root: PathBuf,
90    /// `default` is the root folder; the rest are `profiles/<name>/`.
91    pub profiles: BTreeMap<String, Profile>,
92    /// O — how the home's boards are worked (`workflow.yaml` at the root; Hermes's dispatcher when there is none).
93    #[serde(default = "super::workflow::hermes_instance")]
94    pub workflow: super::Workflow,
95    /// O — declared agents by name (§2.10); a named profile implies its own agent without one.
96    #[serde(default)]
97    pub agents: BTreeMap<String, AgentDecl>,
98    /// O — conversations by id, separate from the sessions bound to them (G5).
99    #[serde(default)]
100    pub conversations: BTreeMap<String, Conversation>,
101    /// O — transfers between agents, in order (G2).
102    #[serde(default)]
103    pub transfers: Vec<Transfer>,
104    /// O — sessions moved to other conversations, in order (G2).
105    #[serde(default)]
106    pub handoffs: Vec<Handoff>,
107    /// O — usage per session (`<harness>:<id>`), summed per agent (G3).
108    #[serde(default)]
109    pub usage: BTreeMap<String, SessionUsage>,
110}