use openai_harmony::{
chat::Role, load_harmony_encoding, HarmonyEncoding, HarmonyEncodingName, StreamableParser,
};
use std::sync::OnceLock;
use uuid::Uuid;
fn extract_tool_name(recipient: &str) -> String {
if let Some(name) = recipient.strip_prefix("functions.") {
name.to_string()
} else {
recipient.to_string()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HarmonyChannel {
Analysis,
Commentary,
Final,
}
impl HarmonyChannel {
pub fn parse(s: &str) -> Option<Self> {
match s {
"analysis" => Some(Self::Analysis),
"commentary" => Some(Self::Commentary),
"final" => Some(Self::Final),
_ => None,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct HarmonyDelta {
pub analysis_delta: Option<String>,
pub commentary_delta: Option<String>,
pub final_delta: Option<String>,
pub current_channel: Option<HarmonyChannel>,
}
impl HarmonyDelta {
pub fn has_content(&self) -> bool {
self.analysis_delta.is_some()
|| self.commentary_delta.is_some()
|| self.final_delta.is_some()
}
pub fn reasoning_content(&self) -> Option<String> {
match (&self.analysis_delta, &self.commentary_delta) {
(Some(a), Some(c)) => Some(format!("{}{}", a, c)),
(Some(a), None) => Some(a.clone()),
(None, Some(c)) => Some(c.clone()),
(None, None) => None,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct HarmonyAccumulated {
pub analysis: String,
pub commentary: String,
pub final_content: String,
}
#[derive(Debug, Clone)]
pub struct HarmonyToolCall {
pub id: String,
pub name: String,
pub arguments: String,
}
impl HarmonyAccumulated {
pub fn reasoning_content(&self) -> Option<String> {
let combined = format!("{}{}", self.analysis, self.commentary);
if combined.is_empty() {
None
} else {
Some(combined)
}
}
}
pub struct HarmonyContext {
parser: StreamableParser,
last_analysis_len: usize,
last_commentary_len: usize,
last_final_len: usize,
accumulated: HarmonyAccumulated,
channel: Option<HarmonyChannel>,
sent_reasoning_len: usize,
sent_final_len: usize,
tool_calls: Vec<HarmonyToolCall>,
current_tool_call: Option<(String, String)>,
sent_tool_args_len: usize,
}
impl HarmonyContext {
pub fn new() -> Result<Self, anyhow::Error> {
let encoding = get_harmony_encoding().clone();
let parser = StreamableParser::new(encoding, Some(Role::Assistant))
.map_err(|e| anyhow::anyhow!("Failed to create Harmony parser: {:?}", e))?;
Ok(Self {
parser,
last_analysis_len: 0,
last_commentary_len: 0,
last_final_len: 0,
accumulated: HarmonyAccumulated::default(),
channel: None,
sent_reasoning_len: 0,
sent_final_len: 0,
tool_calls: Vec::new(),
current_tool_call: None,
sent_tool_args_len: 0,
})
}
pub fn process_token(&mut self, token_id: u32) -> HarmonyDelta {
let _ = self.parser.process(token_id);
self.extract_delta()
}
fn extract_delta(&mut self) -> HarmonyDelta {
let mut delta = HarmonyDelta::default();
if let Some(channel_str) = self.parser.current_channel() {
if let Some(channel) = HarmonyChannel::parse(&channel_str) {
self.channel = Some(channel);
delta.current_channel = Some(channel);
}
}
let current_recipient = self.parser.current_recipient();
if let Ok(content) = self.parser.current_content() {
if let Some(ref recipient) = current_recipient {
let is_tool_call = recipient.starts_with("functions.")
|| recipient.starts_with("browser.")
|| recipient == "python";
if is_tool_call {
let is_same_tool_call = self
.current_tool_call
.as_ref()
.is_some_and(|(existing, _)| existing == recipient);
if is_same_tool_call {
if let Some((_, ref mut args)) = self.current_tool_call {
*args = content.clone();
}
} else {
if let Some((prev_recipient, prev_args)) = self.current_tool_call.take() {
let prev_name = extract_tool_name(&prev_recipient);
self.tool_calls.push(HarmonyToolCall {
id: format!("call_{}", Uuid::new_v4()),
name: prev_name,
arguments: prev_args,
});
}
self.current_tool_call = Some((recipient.clone(), content.clone()));
self.sent_tool_args_len = 0;
}
return delta;
}
}
match self.channel {
Some(HarmonyChannel::Analysis) => {
if content.len() > self.last_analysis_len {
let new_content = content[self.last_analysis_len..].to_string();
self.accumulated.analysis.push_str(&new_content);
delta.analysis_delta = Some(new_content);
self.last_analysis_len = content.len();
}
}
Some(HarmonyChannel::Commentary) => {
if content.len() > self.last_commentary_len {
let new_content = content[self.last_commentary_len..].to_string();
self.accumulated.commentary.push_str(&new_content);
delta.commentary_delta = Some(new_content);
self.last_commentary_len = content.len();
}
}
Some(HarmonyChannel::Final) | None => {
if content.len() > self.last_final_len {
let new_content = content[self.last_final_len..].to_string();
self.accumulated.final_content.push_str(&new_content);
delta.final_delta = Some(new_content);
self.last_final_len = content.len();
}
}
}
}
delta
}
pub fn current_channel(&self) -> Option<HarmonyChannel> {
self.channel
}
pub fn accumulated(&self) -> &HarmonyAccumulated {
&self.accumulated
}
pub fn reasoning_content(&self) -> Option<String> {
self.accumulated.reasoning_content()
}
pub fn final_content(&self) -> Option<String> {
if self.accumulated.final_content.is_empty() {
None
} else {
Some(self.accumulated.final_content.clone())
}
}
pub fn get_reasoning_delta(&mut self) -> Option<String> {
let reasoning = format!(
"{}{}",
self.accumulated.analysis, self.accumulated.commentary
);
if reasoning.len() > self.sent_reasoning_len {
let delta = reasoning[self.sent_reasoning_len..].to_string();
self.sent_reasoning_len = reasoning.len();
if delta.is_empty() {
None
} else {
Some(delta)
}
} else {
None
}
}
pub fn get_final_delta(&mut self) -> Option<String> {
if self.accumulated.final_content.len() > self.sent_final_len {
let delta = self.accumulated.final_content[self.sent_final_len..].to_string();
self.sent_final_len = self.accumulated.final_content.len();
if delta.is_empty() {
None
} else {
Some(delta)
}
} else {
None
}
}
pub fn process_eos(&mut self) {
let _ = self.parser.process_eos();
if let Some((recipient, args)) = self.current_tool_call.take() {
let name = extract_tool_name(&recipient);
self.tool_calls.push(HarmonyToolCall {
id: format!("call_{}", Uuid::new_v4()),
name,
arguments: args,
});
}
}
pub fn current_recipient(&self) -> Option<String> {
self.parser.current_recipient()
}
pub fn has_tool_call(&self) -> bool {
self.current_tool_call.is_some() || !self.tool_calls.is_empty()
}
pub fn get_tool_calls(&self) -> &[HarmonyToolCall] {
&self.tool_calls
}
pub fn get_current_tool_call(&self) -> Option<(&str, &str)> {
self.current_tool_call
.as_ref()
.map(|(recipient, args)| (recipient.as_str(), args.as_str()))
}
pub fn finalize_tool_calls(&mut self) -> Vec<HarmonyToolCall> {
if let Some((recipient, args)) = self.current_tool_call.take() {
let name = extract_tool_name(&recipient);
self.tool_calls.push(HarmonyToolCall {
id: format!("call_{}", Uuid::new_v4()),
name,
arguments: args,
});
}
std::mem::take(&mut self.tool_calls)
}
}
impl super::ReasoningParser for HarmonyContext {
fn process_bytes(&mut self, _bytes: &[u8]) {
}
fn process_token(&mut self, token_id: u32) {
let _ = Self::process_token(self, token_id);
}
fn finalize(&mut self) {
Self::process_eos(self);
}
fn get_content_delta(&mut self) -> Option<String> {
Self::get_final_delta(self)
}
fn get_reasoning_delta(&mut self) -> Option<String> {
Self::get_reasoning_delta(self)
}
fn content(&self) -> Option<String> {
Self::final_content(self)
}
fn reasoning_content(&self) -> Option<String> {
Self::reasoning_content(self)
}
fn has_tool_calls(&self) -> bool {
Self::has_tool_call(self)
}
fn finalize_tool_calls(&mut self) -> Vec<HarmonyToolCall> {
Self::finalize_tool_calls(self)
}
}
static HARMONY_ENCODING: OnceLock<HarmonyEncoding> = OnceLock::new();
pub fn prewarm_harmony_encoding() {
let _ = HARMONY_ENCODING.get_or_init(|| {
load_harmony_encoding(HarmonyEncodingName::HarmonyGptOss)
.expect("Failed to load Harmony encoding")
});
}
pub fn is_harmony_encoding_ready() -> bool {
HARMONY_ENCODING.get().is_some()
}
fn get_harmony_encoding() -> &'static HarmonyEncoding {
HARMONY_ENCODING
.get()
.expect("Harmony encoding not initialized. Call prewarm_harmony_encoding() first.")
}
pub fn is_harmony_template(template: &str) -> bool {
if template.contains("<|channel|>") {
return true;
}
template.contains("<|start|>")
&& template.contains("<|message|>")
&& template.contains("<|end|>")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_harmony_template() {
assert!(is_harmony_template(
"<|start|>system<|message|>content<|end|>"
));
assert!(is_harmony_template(
"some prefix <|channel|>analysis<|message|>thinking"
));
assert!(!is_harmony_template("<|im_start|>system<|im_end|>"));
assert!(!is_harmony_template("regular chat template"));
}
#[test]
fn test_harmony_channel_from_str() {
assert_eq!(
HarmonyChannel::parse("analysis"),
Some(HarmonyChannel::Analysis)
);
assert_eq!(
HarmonyChannel::parse("commentary"),
Some(HarmonyChannel::Commentary)
);
assert_eq!(HarmonyChannel::parse("final"), Some(HarmonyChannel::Final));
assert_eq!(HarmonyChannel::parse("unknown"), None);
}
#[test]
fn test_harmony_delta_has_content() {
let empty = HarmonyDelta::default();
assert!(!empty.has_content());
let with_analysis = HarmonyDelta {
analysis_delta: Some("thinking".to_string()),
..Default::default()
};
assert!(with_analysis.has_content());
let with_final = HarmonyDelta {
final_delta: Some("response".to_string()),
..Default::default()
};
assert!(with_final.has_content());
}
#[test]
fn test_harmony_delta_reasoning_content() {
let both = HarmonyDelta {
analysis_delta: Some("thinking ".to_string()),
commentary_delta: Some("about tools".to_string()),
..Default::default()
};
assert_eq!(
both.reasoning_content(),
Some("thinking about tools".to_string())
);
let only_analysis = HarmonyDelta {
analysis_delta: Some("just thinking".to_string()),
..Default::default()
};
assert_eq!(
only_analysis.reasoning_content(),
Some("just thinking".to_string())
);
let none = HarmonyDelta::default();
assert_eq!(none.reasoning_content(), None);
}
}