Skip to main content

Vine/Server/Notification/
OutputChannelAppend.rs

1//! Cocoon `outputChannel.append` notification. Twin of `output.append`;
2//! see `OutputCreate.rs` for the duplicate-wire rationale.
3//!
4//! Tries the per-channel coalescer first; falls back to legacy
5//! per-append emit when `OutputCoalesce=0` is set or when the payload
6//! has no `value` field. Channel-aware dev_log tagging routes Git/SCM
7//! to `grpc`, everything else to `output-verbose`.
8
9use serde_json::Value;
10
11use crate::{Host::VineHost, Server::Notification::OutputChannelCoalesce, dev_log};
12
13pub async fn OutputChannelAppend(Host:&dyn VineHost, Parameter:&Value) {
14	let ChannelName = Parameter
15		.get("channel")
16		.or_else(|| Parameter.get("name"))
17		.and_then(Value::as_str)
18		.unwrap_or("?");
19
20	let TextValue = Parameter.get("value").and_then(Value::as_str);
21
22	let CoalesceEnqueued = match TextValue {
23		Some(Text) => {
24			OutputChannelCoalesce::TryEnqueue(Host.RendererEmitter(), ChannelName.to_string(), Text.to_string())
25		},
26
27		None => false,
28	};
29
30	if CoalesceEnqueued {
31		return;
32	}
33
34	Host.EmitToRenderer("sky://output/append", Parameter.clone());
35
36	// Char-aware truncation. Slicing at `&S[..200]` panics when byte
37	// 200 lands inside a multi-byte UTF-8 codepoint (vscode.git's
38	// progress messages contain `•` which is 3 bytes); walk char
39	// boundaries instead.
40	let TruncatedValue = Parameter
41		.get("value")
42		.and_then(Value::as_str)
43		.map(|S| {
44			if S.len() > 200 {
45				let CutAt = S
46					.char_indices()
47					.map(|(Index, _)| Index)
48					.take_while(|Index| *Index <= 200)
49					.last()
50					.unwrap_or(0);
51
52				format!("{}…", &S[..CutAt])
53			} else {
54				S.to_string()
55			}
56		})
57		.unwrap_or_else(|| "<no-value>".to_string());
58
59	if ChannelName.eq_ignore_ascii_case("git")
60		|| ChannelName.eq_ignore_ascii_case("source control")
61		|| ChannelName.eq_ignore_ascii_case("scm")
62	{
63		dev_log!(
64			"grpc",
65			"[OutputChannel:{}] {}",
66			ChannelName,
67			TruncatedValue.trim_end_matches('\n')
68		);
69	} else {
70		dev_log!("output-verbose", "[OutputChannel] append channel={}", ChannelName);
71	}
72}