58
return [Number(match[1]), Number(match[2]), Number(match[3])] as const;
59
}
61
>
/**
62
>
* Compares two `MAJOR.MINOR.PATCH` SemVer strings.
63
>
*
64
>
* Returns a negative number if `a < b`, zero if `a === b`, and a positive
65
>
* number if `a > b`.
66
>
*/
67
>
export function compareProtocolVersions(a: string, b: string): number {
68
const [aMajor, aMinor, aPatch] = parseSemver(a);
69
const [bMajor, bMinor, bPatch] = parseSemver(b);
70
return (aMajor - bMajor) || (aMinor - bMinor) || (aPatch - bPatch);
71
}
73
>
// ─── Exhaustive Action → Version Map ─────────────────────────────────────────
74
>
75
>
/**
76
>
* Maps every action type to the protocol version that introduced it.
77
>
* Adding a new action to `StateAction` without adding it here is a compile error.
78
>
*
79
>
* Versions are SemVer `MAJOR.MINOR.PATCH` strings (see `PROTOCOL_VERSION`).
80
>
*/
81
>
export const ACTION_INTRODUCED_IN: { readonly [K in StateAction['type']]: string } = {
82
>
[ActionType.RootAgentsChanged]: '0.1.0',
83
>
[ActionType.RootActiveSessionsChanged]: '0.1.0',
84
>
[ActionType.SessionReady]: '0.1.0',
85
>
[ActionType.SessionCreationFailed]: '0.1.0',
86
>
[ActionType.SessionChatAdded]: '0.4.0',
87
>
[ActionType.SessionChatRemoved]: '0.4.0',
88
>
[ActionType.SessionChatUpdated]: '0.4.0',
89
>
[ActionType.SessionDefaultChatChanged]: '0.4.0',
90
>
[ActionType.SessionTitleChanged]: '0.1.0',
91
>
[ActionType.SessionServerToolsChanged]: '0.1.0',
92
>
[ActionType.SessionActiveClientSet]: '0.5.0',
93
>
[ActionType.SessionActiveClientRemoved]: '0.5.0',
94
>
[ActionType.SessionWorkingDirectorySet]: '0.7.0',
95
>
[ActionType.SessionWorkingDirectoryRemoved]: '0.7.0',
96
>
[ActionType.SessionInputNeededSet]: '0.5.1',
97
>
[ActionType.SessionInputNeededRemoved]: '0.5.1',
98
>
[ActionType.SessionCustomizationsChanged]: '0.1.0',
99
>
[ActionType.SessionCustomizationToggled]: '0.1.0',
100
>
[ActionType.SessionCustomizationUpdated]: '0.1.0',
101
>
[ActionType.SessionCustomizationRemoved]: '0.2.0',
102
>
[ActionType.SessionMcpServerStateChanged]: '0.3.0',
103
>
[ActionType.SessionMcpServerStartRequested]: '0.5.2',
104
>
[ActionType.SessionMcpServerStopRequested]: '0.5.2',
105
>
[ActionType.SessionIsReadChanged]: '0.1.0',
106
>
[ActionType.SessionIsArchivedChanged]: '0.1.0',
107
>
[ActionType.SessionActivityChanged]: '0.1.0',
108
>
[ActionType.SessionChangesetsChanged]: '0.2.0',
109
>
[ActionType.SessionConfigChanged]: '0.1.0',
110
>
[ActionType.SessionMetaChanged]: '0.1.0',
111
>
[ActionType.ChatTurnStarted]: '0.4.0',
112
>
[ActionType.ChatDelta]: '0.4.0',
113
>
[ActionType.ChatResponsePart]: '0.4.0',
114
>
[ActionType.ChatToolCallStart]: '0.4.0',
115
>
[ActionType.ChatToolCallDelta]: '0.4.0',
116
>
[ActionType.ChatToolCallReady]: '0.4.0',
117
>
[ActionType.ChatToolCallConfirmed]: '0.4.0',
118
>
[ActionType.ChatToolCallComplete]: '0.4.0',
119
>
[ActionType.ChatToolCallResultConfirmed]: '0.4.0',
120
>
[ActionType.ChatToolCallContentChanged]: '0.4.0',
121
>
[ActionType.ChatToolCallAuthRequired]: '0.6.0',
122
>
[ActionType.ChatToolCallAuthResolved]: '0.6.0',
123
>
[ActionType.ChatTurnComplete]: '0.4.0',
124
>
[ActionType.ChatTurnCancelled]: '0.4.0',
125
>
[ActionType.ChatError]: '0.4.0',
126
>
[ActionType.ChatActivityChanged]: '0.5.0',
127
>
[ActionType.ChatWorkingDirectorySet]: '0.7.0',
128
>
[ActionType.ChatWorkingDirectoryRemoved]: '0.7.0',
129
>
[ActionType.ChatUsage]: '0.4.0',
130
>
[ActionType.ChatReasoning]: '0.4.0',
131
>
[ActionType.ChatPendingMessageSet]: '0.4.0',
132
>
[ActionType.ChatPendingMessageRemoved]: '0.4.0',
133
>
[ActionType.ChatQueuedMessagesReordered]: '0.4.0',
134
>
[ActionType.ChatDraftChanged]: '0.5.0',
135
>
[ActionType.ChatInputRequested]: '0.4.0',
136
>
[ActionType.ChatInputAnswerChanged]: '0.4.0',
137
>
[ActionType.ChatInputCompleted]: '0.4.0',
138
>
[ActionType.ChatTruncated]: '0.4.0',
139
>
[ActionType.ChatTurnsLoaded]: '0.5.1',
140
>
[ActionType.ChangesetStatusChanged]: '0.2.0',
141
>
[ActionType.ChangesetFileSet]: '0.2.0',
142
>
[ActionType.ChangesetFileRemoved]: '0.2.0',
143
>
[ActionType.ChangesetFilesReviewChanged]: '0.6.0',
144
>
[ActionType.ChangesetContentChanged]: '0.4.0',
145
>
[ActionType.ChangesetOperationsChanged]: '0.2.0',
146
>
[ActionType.ChangesetOperationStatusChanged]: '0.3.0',
147
>
[ActionType.ChangesetCleared]: '0.2.0',
148
>
[ActionType.AnnotationsSet]: '0.4.0',
149
>
[ActionType.AnnotationsUpdated]: '0.4.0',
150
>
[ActionType.AnnotationsRemoved]: '0.4.0',
151
>
[ActionType.AnnotationsEntrySet]: '0.4.0',
152
>
[ActionType.AnnotationsEntryRemoved]: '0.4.0',
153
>
[ActionType.RootTerminalsChanged]: '0.1.0',
154
>
[ActionType.RootConfigChanged]: '0.1.0',
155
>
[ActionType.TerminalData]: '0.1.0',
156
>
[ActionType.TerminalInput]: '0.1.0',
157
>
[ActionType.TerminalResized]: '0.1.0',
158
>
[ActionType.TerminalClaimed]: '0.1.0',
159
>
[ActionType.TerminalTitleChanged]: '0.1.0',
160
>
[ActionType.TerminalCwdChanged]: '0.1.0',
161
>
[ActionType.TerminalExited]: '0.1.0',
162
>
[ActionType.TerminalCleared]: '0.1.0',
163
>
[ActionType.TerminalCommandDetectionAvailable]: '0.1.0',
164
>
[ActionType.TerminalCommandExecuted]: '0.1.0',
165
>
[ActionType.TerminalCommandFinished]: '0.1.0',
166
>
[ActionType.ResourceWatchChanged]: '0.2.0',
167
>
};
168
>
169
>
/**
170
>
* Returns whether the given action type is known to the specified protocol version.
171
>
*/
172
>
export function isActionKnownToVersion(action: StateAction, clientVersion: string): boolean {
173
return compareProtocolVersions(ACTION_INTRODUCED_IN[action.type], clientVersion) <= 0;
174
}
176
>
// ─── Exhaustive Notification Method → Version Map ──────────────────────────
177
>
178
>
/**
179
>
* Server → client notification method names that are part of the AHP
180
>
* protocol surface. The set is a subset of {@link ServerNotificationMap}
181
>
* keys that excludes `action` (the action envelope) since action versions
182
>
* are tracked via {@link ACTION_INTRODUCED_IN}.
183
>
*/
184
>
export type ProtocolNotificationMethod = Exclude<keyof ServerNotificationMap, 'action'>;
185
>
186
>
/**
187
>
* Maps every server → client protocol notification method to the protocol
188
>
* version that introduced it. Adding a new notification method to
189
>
* {@link ServerNotificationMap} without adding it here is a compile error.
190
>
*
191
>
* Versions are SemVer `MAJOR.MINOR.PATCH` strings (see `PROTOCOL_VERSION`).
192
>
*/
193
>
export const NOTIFICATION_INTRODUCED_IN: { readonly [K in ProtocolNotificationMethod]: string } = {
194
>
'root/sessionAdded': '0.1.0',
195
>
'root/sessionRemoved': '0.1.0',
196
>
'root/sessionSummaryChanged': '0.1.0',
197
>
'root/progress': '0.5.0',
198
>
'auth/required': '0.1.0',
199
>
'otlp/exportLogs': '0.2.0',
200
>
'otlp/exportTraces': '0.2.0',
201
>
'otlp/exportMetrics': '0.2.0',
202
>
};
203
>
204
>
/**
205
>
* Returns whether the given notification method is known to the specified
206
>
* protocol version.
207
>
*/
208
>
export function isNotificationKnownToVersion(method: ProtocolNotificationMethod, clientVersion: string): boolean {
209
return compareProtocolVersions(NOTIFICATION_INTRODUCED_IN[method], clientVersion) <= 0;
210
}