1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Dialect binding reported by a Connector after open/negotiation.
use serde::{Deserialize, Serialize};
/// High-level dialect family (not an encoder/decoder implementation).
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum DialectFamily {
/// OpenAI Chat Completions v1 (streaming SSE) — first direct-LLM dialect.
OpenAiChatCompletions,
/// OpenAI Responses-style SSE (later dialect).
OpenAiResponses,
/// Anthropic Messages SSE.
AnthropicMessages,
/// Agent Client Protocol / JSON-RPC.
Acp,
/// Cursor ACP profile.
CursorAcp,
/// Google Antigravity (`agy`) ACP profile (stdio NDJSON / agy-acp bridge).
AgyAcp,
/// OpenAI Codex ACP profile (stdio NDJSON / codex-acp adapter).
CodexAcp,
/// Z.ai CLI headless profile: OpenAI-compatible chat message NDJSON on stdout.
ZaiCli,
/// Claude Code headless profile: `claude -p --output-format stream-json` NDJSON.
ClaudeCode,
/// Grok Build ACP/JSONL profile family tag.
GrokBuild,
/// Deterministic test dialect.
Test,
/// Extension point with bounded name.
Other(String),
}
/// How the dialect was selected for a connection.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum DialectNegotiation {
/// Fixed by connector configuration / profile.
Fixed,
/// Negotiated during open/handshake and then frozen.
Negotiated,
}
/// Stable, bounded, versioned dialect descriptor.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct DialectDescriptor {
/// Dialect family.
pub family: DialectFamily,
/// Version string (e.g. `"v1"`).
pub version: String,
/// Framing (e.g. `"sse"`, `"json_rpc"`, `"jsonl"`).
pub framing: String,
/// Optional profile qualifier (e.g. `"grok_build"`).
pub profile: Option<String>,
}
impl DialectDescriptor {
/// OpenAI Chat Completions streaming SSE (direct-LLM).
pub fn openai_chat_completions(version: impl Into<String>) -> Self {
Self {
family: DialectFamily::OpenAiChatCompletions,
version: version.into(),
framing: "sse".into(),
profile: Some("openai_chat_completions".into()),
}
}
/// ACP / JSON-RPC dialect used by Grok Build.
pub fn acp_json_rpc(version: impl Into<String>) -> Self {
Self {
family: DialectFamily::Acp,
version: version.into(),
framing: "json_rpc".into(),
profile: Some("grok_build".into()),
}
}
/// Cursor Agent ACP over stdio (newline-delimited JSON-RPC).
pub fn cursor_acp(version: impl Into<String>) -> Self {
Self {
family: DialectFamily::CursorAcp,
version: version.into(),
framing: "ndjson".into(),
profile: Some("cursor".into()),
}
}
/// Antigravity / agy ACP over stdio (native or `agy-acp` bridge).
pub fn agy_acp(version: impl Into<String>) -> Self {
Self {
family: DialectFamily::AgyAcp,
version: version.into(),
framing: "ndjson".into(),
profile: Some("antigravity".into()),
}
}
/// OpenAI Codex ACP over stdio (`@agentclientprotocol/codex-acp` adapter).
pub fn codex_acp(version: impl Into<String>) -> Self {
Self {
family: DialectFamily::CodexAcp,
version: version.into(),
framing: "ndjson".into(),
profile: Some("codex".into()),
}
}
/// Z.ai CLI headless (`zai -p`): OpenAI-compatible chat messages as NDJSON lines.
pub fn zai_cli(version: impl Into<String>) -> Self {
Self {
family: DialectFamily::ZaiCli,
version: version.into(),
framing: "ndjson".into(),
profile: Some("zai".into()),
}
}
/// Claude Code headless (`claude -p --output-format stream-json --verbose`).
pub fn claude_code(version: impl Into<String>) -> Self {
Self {
family: DialectFamily::ClaudeCode,
version: version.into(),
framing: "ndjson".into(),
profile: Some("claude_code".into()),
}
}
/// Deterministic in-memory test dialect.
pub fn test_raw() -> Self {
Self {
family: DialectFamily::Test,
version: "v1".into(),
framing: "raw".into(),
profile: Some("fake".into()),
}
}
}
/// Immutable input/output dialect pair for one opened connection.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct DialectBinding {
/// Bytes written to the external system use this dialect.
pub input: DialectDescriptor,
/// Bytes read from the external system use this dialect.
pub output: DialectDescriptor,
/// Whether dialects were fixed or negotiated.
pub negotiation: DialectNegotiation,
}
impl DialectBinding {
/// Fixed identical input/output dialect.
pub fn fixed(dialect: DialectDescriptor) -> Self {
Self {
input: dialect.clone(),
output: dialect,
negotiation: DialectNegotiation::Fixed,
}
}
/// Negotiated identical input/output dialect (frozen at open).
pub fn negotiated(dialect: DialectDescriptor) -> Self {
Self {
input: dialect.clone(),
output: dialect,
negotiation: DialectNegotiation::Negotiated,
}
}
}