1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
4#[serde(rename_all = "camelCase")]
5pub struct AppServerMethodSpec {
6 pub method: &'static str,
7 pub params_type: String,
8 pub result_type: String,
9 pub stability: AppServerMethodStability,
10 pub feature_group: &'static str,
11 pub idempotency: AppServerIdempotency,
12 pub side_effect: AppServerSideEffect,
13 #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
14 pub notifications: &'static [&'static str],
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
18#[serde(rename_all = "camelCase")]
19pub enum AppServerMethodStability {
20 Stable,
21 Experimental,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub enum AppServerIdempotency {
27 Idempotent,
28 NonIdempotent,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub enum AppServerSideEffect {
34 ReadOnly,
35 LocalState,
36 ExternalProcess,
37}
38
39#[derive(Debug, Clone, PartialEq, Serialize)]
40#[serde(rename_all = "camelCase")]
41pub struct AppServerMethodManifest {
42 pub schema_version: u32,
43 pub unknown_methods_allowed: bool,
44 pub methods: Vec<AppServerMethodSpec>,
45}
46
47pub const APP_SERVER_METHOD_MANIFEST_VERSION: u32 = 1;
48
49pub fn app_server_method_manifest() -> AppServerMethodManifest {
50 AppServerMethodManifest {
51 schema_version: APP_SERVER_METHOD_MANIFEST_VERSION,
52 unknown_methods_allowed: true,
53 methods: app_server_method_specs(),
54 }
55}
56
57pub fn app_server_method_specs() -> Vec<AppServerMethodSpec> {
58 METHOD_SPECS
59 .iter()
60 .map(|seed| AppServerMethodSpec {
61 method: seed.method,
62 params_type: method_type_name(seed.method, "Params"),
63 result_type: method_type_name(seed.method, "Result"),
64 stability: seed.stability,
65 feature_group: seed.feature_group,
66 idempotency: seed.idempotency,
67 side_effect: seed.side_effect,
68 notifications: seed.notifications,
69 })
70 .collect()
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74struct AppServerMethodSpecSeed {
75 method: &'static str,
76 stability: AppServerMethodStability,
77 feature_group: &'static str,
78 idempotency: AppServerIdempotency,
79 side_effect: AppServerSideEffect,
80 notifications: &'static [&'static str],
81}
82
83fn method_type_name(method: &str, suffix: &str) -> String {
84 if let Some(name) = explicit_method_type_name(method, suffix) {
85 return name.to_string();
86 }
87 let mut name = String::new();
88 let mut capitalize_next = true;
89 for ch in method.chars() {
90 if ch.is_ascii_alphanumeric() {
91 if capitalize_next {
92 name.push(ch.to_ascii_uppercase());
93 capitalize_next = false;
94 } else {
95 name.push(ch);
96 }
97 } else {
98 capitalize_next = true;
99 }
100 }
101 name.push_str(suffix);
102 name
103}
104
105fn explicit_method_type_name(method: &str, suffix: &str) -> Option<&'static str> {
106 match (method, suffix) {
107 ("vcs/status", "Params") | ("vcs/lines/list", "Params") => Some("VcsWorkspaceParams"),
108 ("vcs/status", "Result") => Some("VcsStatus"),
109 ("vcs/changes/read", "Result") => Some("VcsChangedContentPage"),
110 ("vcs/lines/list", "Result") => Some("Vec<VcsLineOfWork>"),
111 ("vcs/lines/switch", "Params") => Some("VcsLineSwitchParams"),
112 ("vcs/lines/switch", "Result")
113 | ("vcs/restore", "Result")
114 | ("vcs/select", "Result")
115 | ("vcs/sync", "Result") => Some("VcsOperationResult"),
116 ("vcs/select", "Params") => Some("VcsSelectionParams"),
117 ("vcs/snapshot/create", "Result") => Some("VcsSnapshot"),
118 _ => None,
119 }
120}
121
122macro_rules! method_spec {
123 ($method:literal, $group:literal, $effect:ident, $idem:ident) => {
124 AppServerMethodSpecSeed {
125 method: $method,
126 stability: AppServerMethodStability::Stable,
127 feature_group: $group,
128 idempotency: AppServerIdempotency::$idem,
129 side_effect: AppServerSideEffect::$effect,
130 notifications: &[],
131 }
132 };
133 ($method:literal, $group:literal, $effect:ident, $idem:ident, [$($notification:literal),+ $(,)?]) => {
134 AppServerMethodSpecSeed {
135 method: $method,
136 stability: AppServerMethodStability::Stable,
137 feature_group: $group,
138 idempotency: AppServerIdempotency::$idem,
139 side_effect: AppServerSideEffect::$effect,
140 notifications: &[$($notification),+],
141 }
142 };
143}
144
145const METHOD_SPECS: &[AppServerMethodSpecSeed] = &[
146 method_spec!("agents/list", "agents", ReadOnly, Idempotent),
147 method_spec!("artifact/delete", "artifacts", LocalState, NonIdempotent),
148 method_spec!("artifact/grep", "artifacts", ReadOnly, Idempotent),
149 method_spec!("artifact/list", "artifacts", ReadOnly, Idempotent),
150 method_spec!("artifact/read", "artifacts", ReadOnly, Idempotent),
151 method_spec!("artifact/tail", "artifacts", ReadOnly, Idempotent),
152 method_spec!("auth/codex/login", "auth", ExternalProcess, NonIdempotent),
153 method_spec!("auth/codex/logout", "auth", LocalState, NonIdempotent),
154 method_spec!("auth/codex/status", "auth", ReadOnly, Idempotent),
155 method_spec!(
156 "auth/supergrok/login",
157 "auth",
158 ExternalProcess,
159 NonIdempotent
160 ),
161 method_spec!("auth/supergrok/logout", "auth", LocalState, NonIdempotent),
162 method_spec!("auth/supergrok/status", "auth", ReadOnly, Idempotent),
163 method_spec!(
164 "auth/kimi-code/login",
165 "auth",
166 ExternalProcess,
167 NonIdempotent
168 ),
169 method_spec!("auth/kimi-code/logout", "auth", LocalState, NonIdempotent),
170 method_spec!("auth/kimi-code/status", "auth", ReadOnly, Idempotent),
171 method_spec!(
172 "automations/cancelRun",
173 "automations",
174 LocalState,
175 NonIdempotent
176 ),
177 method_spec!(
178 "automations/create",
179 "automations",
180 LocalState,
181 NonIdempotent
182 ),
183 method_spec!(
184 "automations/delete",
185 "automations",
186 LocalState,
187 NonIdempotent
188 ),
189 method_spec!("automations/list", "automations", ReadOnly, Idempotent),
190 method_spec!(
191 "automations/runNow",
192 "automations",
193 LocalState,
194 NonIdempotent
195 ),
196 method_spec!("automations/runs", "automations", ReadOnly, Idempotent),
197 method_spec!("automations/status", "automations", ReadOnly, Idempotent),
198 method_spec!(
199 "automations/update",
200 "automations",
201 LocalState,
202 NonIdempotent
203 ),
204 method_spec!("chrome/browsers/list", "chrome", ReadOnly, Idempotent),
205 method_spec!("chrome/debug/console", "chrome", ReadOnly, Idempotent),
206 method_spec!("chrome/debug/network", "chrome", ReadOnly, Idempotent),
207 method_spec!("chrome/disable", "chrome", LocalState, NonIdempotent),
208 method_spec!("chrome/enable", "chrome", LocalState, NonIdempotent),
209 method_spec!(
210 "chrome/page/action",
211 "chrome",
212 ExternalProcess,
213 NonIdempotent
214 ),
215 method_spec!("chrome/page/snapshot", "chrome", ReadOnly, Idempotent),
216 method_spec!("chrome/permissions/list", "chrome", ReadOnly, Idempotent),
217 method_spec!(
218 "chrome/permissions/update",
219 "chrome",
220 LocalState,
221 NonIdempotent
222 ),
223 method_spec!("chrome/reconnect", "chrome", ReadOnly, Idempotent),
224 method_spec!("chrome/setMode", "chrome", LocalState, NonIdempotent),
225 method_spec!("chrome/status", "chrome", ReadOnly, Idempotent),
226 method_spec!(
227 "chrome/tabs/activate",
228 "chrome",
229 ExternalProcess,
230 NonIdempotent
231 ),
232 method_spec!("chrome/tabs/list", "chrome", ReadOnly, Idempotent),
233 method_spec!(
234 "chrome/tabs/navigate",
235 "chrome",
236 ExternalProcess,
237 NonIdempotent
238 ),
239 method_spec!("command/exec", "commands", ExternalProcess, NonIdempotent),
240 method_spec!("commands/expand", "commands", ReadOnly, Idempotent),
241 method_spec!("commands/list", "commands", ReadOnly, Idempotent),
242 method_spec!("commands/run", "commands", LocalState, NonIdempotent),
243 method_spec!("design/batch_get", "design", ReadOnly, Idempotent),
244 method_spec!(
245 "design/export_nodes",
246 "design",
247 LocalState,
248 NonIdempotent,
249 ["design/exportCompleted"]
250 ),
251 method_spec!("design/get_editor_state", "design", ReadOnly, Idempotent),
252 method_spec!("design/get_guidelines", "design", ReadOnly, Idempotent),
253 method_spec!("design/get_screenshot", "design", ReadOnly, Idempotent),
254 method_spec!("design/get_variables", "design", ReadOnly, Idempotent),
255 method_spec!(
256 "design/patch",
257 "design",
258 LocalState,
259 NonIdempotent,
260 ["design/documentChanged"]
261 ),
262 method_spec!("design/read", "design", ReadOnly, Idempotent),
263 method_spec!(
264 "design/set_selection",
265 "design",
266 LocalState,
267 NonIdempotent,
268 ["design/selectionChanged"]
269 ),
270 method_spec!(
271 "design/set_variables",
272 "design",
273 LocalState,
274 NonIdempotent,
275 ["design/documentChanged"]
276 ),
277 method_spec!("design/snapshot_layout", "design", ReadOnly, Idempotent),
278 method_spec!("design/spawn_agents", "design", ReadOnly, NonIdempotent),
279 method_spec!("discovery/groups", "discovery", ReadOnly, Idempotent),
280 method_spec!("discovery/promote", "discovery", LocalState, NonIdempotent),
281 method_spec!(
282 "discovery/promoted/clear",
283 "discovery",
284 LocalState,
285 NonIdempotent
286 ),
287 method_spec!("discovery/promoted/list", "discovery", ReadOnly, Idempotent),
288 method_spec!("discovery/read", "discovery", ReadOnly, Idempotent),
289 method_spec!("discovery/refresh", "discovery", LocalState, NonIdempotent),
290 method_spec!("discovery/search", "discovery", ReadOnly, Idempotent),
291 method_spec!("eval/report/read", "eval", ReadOnly, Idempotent),
292 method_spec!("eval/reports/list", "eval", ReadOnly, Idempotent),
293 method_spec!("extensions/list", "extensions", ReadOnly, Idempotent),
294 method_spec!("forks/create", "forks", LocalState, NonIdempotent),
295 method_spec!("forks/list", "forks", ReadOnly, Idempotent),
296 method_spec!("forks/providers/list", "forks", ReadOnly, Idempotent),
297 method_spec!("forks/remove", "forks", LocalState, NonIdempotent),
298 method_spec!("fs/readDirectory", "filesystem", ReadOnly, Idempotent),
299 method_spec!("fs/readFile", "filesystem", ReadOnly, Idempotent),
300 method_spec!("hosted/audit/list", "hosted", ReadOnly, Idempotent),
301 method_spec!("hosted/hooks/create", "hosted", LocalState, NonIdempotent),
302 method_spec!("hosted/hooks/delete", "hosted", LocalState, NonIdempotent),
303 method_spec!("hosted/hooks/list", "hosted", ReadOnly, Idempotent),
304 method_spec!("hosted/hooks/update", "hosted", LocalState, NonIdempotent),
305 method_spec!(
306 "hosted/service_accounts/create",
307 "hosted",
308 LocalState,
309 NonIdempotent
310 ),
311 method_spec!(
312 "hosted/service_accounts/list",
313 "hosted",
314 ReadOnly,
315 Idempotent
316 ),
317 method_spec!(
318 "hosted/service_accounts/revoke",
319 "hosted",
320 LocalState,
321 NonIdempotent
322 ),
323 method_spec!("hosted/tenant/read", "hosted", ReadOnly, Idempotent),
324 method_spec!("hosted/tenants/list", "hosted", ReadOnly, Idempotent),
325 method_spec!("hosted/usage/read", "hosted", ReadOnly, Idempotent),
326 method_spec!("hosted/whoami", "hosted", ReadOnly, Idempotent),
327 method_spec!("hunk/list", "plan-review", ReadOnly, Idempotent),
328 method_spec!("hunk/read", "plan-review", ReadOnly, Idempotent),
329 method_spec!("hunk/rollback", "plan-review", LocalState, NonIdempotent),
330 method_spec!("index/proofs/list", "code-index", ReadOnly, Idempotent),
331 method_spec!("index/readChunk", "code-index", ReadOnly, Idempotent),
332 method_spec!("index/rebuild", "code-index", LocalState, NonIdempotent),
333 method_spec!("index/search", "code-index", ReadOnly, Idempotent),
334 method_spec!("index/status", "code-index", ReadOnly, Idempotent),
335 method_spec!(
336 "inference/routing/metrics",
337 "inference",
338 ReadOnly,
339 Idempotent
340 ),
341 method_spec!(
342 "inference/routing/status",
343 "inference",
344 ReadOnly,
345 Idempotent
346 ),
347 method_spec!("initialize", "app", ReadOnly, Idempotent),
348 method_spec!("knowledge/delete", "knowledge", LocalState, NonIdempotent),
349 method_spec!(
350 "knowledge/links/set",
351 "knowledge",
352 LocalState,
353 NonIdempotent
354 ),
355 method_spec!("knowledge/list", "knowledge", ReadOnly, Idempotent),
356 method_spec!("knowledge/read", "knowledge", ReadOnly, Idempotent),
357 method_spec!(
358 "knowledge/revisions/list",
359 "knowledge",
360 ReadOnly,
361 Idempotent
362 ),
363 method_spec!("knowledge/save", "knowledge", LocalState, NonIdempotent),
364 method_spec!("knowledge/search", "knowledge", ReadOnly, Idempotent),
365 method_spec!("knowledge/update", "knowledge", LocalState, NonIdempotent),
366 method_spec!(
367 "marketplaces/add",
368 "marketplaces",
369 LocalState,
370 NonIdempotent
371 ),
372 method_spec!(
373 "marketplaces/install_default",
374 "marketplaces",
375 LocalState,
376 NonIdempotent
377 ),
378 method_spec!("marketplaces/list", "marketplaces", ReadOnly, Idempotent),
379 method_spec!("marketplaces/plugin", "marketplaces", ReadOnly, Idempotent),
380 method_spec!(
381 "marketplaces/refresh",
382 "marketplaces",
383 LocalState,
384 NonIdempotent
385 ),
386 method_spec!(
387 "marketplaces/remove",
388 "marketplaces",
389 LocalState,
390 NonIdempotent
391 ),
392 method_spec!("marketplaces/search", "marketplaces", ReadOnly, Idempotent),
393 method_spec!("media/attachToTurn", "media", LocalState, NonIdempotent),
394 method_spec!("media/delete", "media", LocalState, NonIdempotent),
395 method_spec!("media/image/generate", "media", LocalState, NonIdempotent),
396 method_spec!("media/image/providers/list", "media", ReadOnly, Idempotent),
397 method_spec!("media/list", "media", ReadOnly, Idempotent),
398 method_spec!("media/read", "media", ReadOnly, Idempotent),
399 method_spec!("media/thumbnail", "media", ReadOnly, Idempotent),
400 method_spec!("memory/delete", "memory", LocalState, NonIdempotent),
401 method_spec!("memory/list", "memory", ReadOnly, Idempotent),
402 method_spec!("memory/provider/list", "memory", ReadOnly, Idempotent),
403 method_spec!("memory/provider/set", "memory", LocalState, NonIdempotent),
404 method_spec!("memory/query", "memory", ReadOnly, Idempotent),
405 method_spec!("memory/read", "memory", ReadOnly, Idempotent),
406 method_spec!("memory/recall/preview", "memory", ReadOnly, Idempotent),
407 method_spec!("memory/save", "memory", LocalState, NonIdempotent),
408 method_spec!("memory/update", "memory", LocalState, NonIdempotent),
409 method_spec!("model/list", "models", ReadOnly, Idempotent),
410 method_spec!("model/select", "models", LocalState, NonIdempotent),
411 method_spec!("node/status", "node", ReadOnly, Idempotent),
412 method_spec!(
413 "packages/approve_extensions",
414 "packages",
415 LocalState,
416 NonIdempotent
417 ),
418 method_spec!(
419 "packages/install",
420 "packages",
421 ExternalProcess,
422 NonIdempotent
423 ),
424 method_spec!("packages/list", "packages", ReadOnly, Idempotent),
425 method_spec!("packages/remove", "packages", LocalState, NonIdempotent),
426 method_spec!(
427 "packages/set_enabled",
428 "packages",
429 LocalState,
430 NonIdempotent
431 ),
432 method_spec!(
433 "packages/set_filters",
434 "packages",
435 LocalState,
436 NonIdempotent
437 ),
438 method_spec!("packages/sync", "packages", ExternalProcess, NonIdempotent),
439 method_spec!(
440 "packages/update",
441 "packages",
442 ExternalProcess,
443 NonIdempotent
444 ),
445 method_spec!(
446 "plan/review/approve",
447 "plan-review",
448 LocalState,
449 NonIdempotent
450 ),
451 method_spec!(
452 "plan/review/comment",
453 "plan-review",
454 LocalState,
455 NonIdempotent
456 ),
457 method_spec!("plan/review/read", "plan-review", ReadOnly, Idempotent),
458 method_spec!(
459 "plan/review/reject",
460 "plan-review",
461 LocalState,
462 NonIdempotent
463 ),
464 method_spec!(
465 "plan/review/rewrite",
466 "plan-review",
467 LocalState,
468 NonIdempotent
469 ),
470 method_spec!("plugins/disable", "plugins", LocalState, NonIdempotent),
471 method_spec!("plugins/install", "plugins", LocalState, NonIdempotent),
472 method_spec!(
473 "plugins/install_all_variants",
474 "plugins",
475 LocalState,
476 NonIdempotent
477 ),
478 method_spec!("plugins/list_installed", "plugins", ReadOnly, Idempotent),
479 method_spec!("plugins/preview_install", "plugins", ReadOnly, Idempotent),
480 method_spec!("plugins/uninstall", "plugins", LocalState, NonIdempotent),
481 method_spec!("processes/get", "processes", ReadOnly, Idempotent),
482 method_spec!("processes/list", "processes", ReadOnly, Idempotent),
483 method_spec!("processes/stop", "processes", LocalState, NonIdempotent),
484 method_spec!("processes/stopAll", "processes", LocalState, NonIdempotent),
485 method_spec!(
486 "processes/subscribe",
487 "processes",
488 ReadOnly,
489 Idempotent,
490 ["processes/changed"]
491 ),
492 method_spec!("providers/clear", "providers", LocalState, NonIdempotent),
493 method_spec!(
494 "providers/configure",
495 "providers",
496 LocalState,
497 NonIdempotent
498 ),
499 method_spec!("providers/list", "providers", ReadOnly, Idempotent),
500 method_spec!("providers/select", "providers", LocalState, NonIdempotent),
501 method_spec!("retrieval/metrics", "retrieval", ReadOnly, Idempotent),
502 method_spec!("retrieval/promoted", "retrieval", ReadOnly, Idempotent),
503 method_spec!(
504 "retrieval/recommendations",
505 "retrieval",
506 ReadOnly,
507 Idempotent
508 ),
509 method_spec!("roadmap/create", "roadmap", LocalState, NonIdempotent),
510 method_spec!("roadmap/list", "roadmap", ReadOnly, Idempotent),
511 method_spec!("roadmap/patch", "roadmap", LocalState, NonIdempotent),
512 method_spec!("roadmap/read", "roadmap", ReadOnly, Idempotent),
513 method_spec!("roadmap/task/update", "roadmap", LocalState, NonIdempotent),
514 method_spec!(
515 "roadmap/thread/attach",
516 "roadmap",
517 LocalState,
518 NonIdempotent
519 ),
520 method_spec!("roadmap/thread/list", "roadmap", ReadOnly, Idempotent),
521 method_spec!(
522 "roadmap/thread/spawn",
523 "roadmap",
524 ExternalProcess,
525 NonIdempotent
526 ),
527 method_spec!("roadmap/validate", "roadmap", ReadOnly, Idempotent),
528 method_spec!("runners/delete", "runners", LocalState, NonIdempotent),
529 method_spec!("runners/list", "runners", ReadOnly, Idempotent),
530 method_spec!("runners/ports", "runners", ReadOnly, Idempotent),
531 method_spec!("runners/select", "runners", LocalState, NonIdempotent),
532 method_spec!("runners/session", "runners", ReadOnly, Idempotent),
533 method_spec!("runners/snapshot", "runners", ReadOnly, Idempotent),
534 method_spec!(
535 "search_index/clear",
536 "search-index",
537 LocalState,
538 NonIdempotent
539 ),
540 method_spec!(
541 "search_index/rebuild",
542 "search-index",
543 LocalState,
544 NonIdempotent
545 ),
546 method_spec!("search_index/status", "search-index", ReadOnly, Idempotent),
547 method_spec!(
548 "search_index/warmup",
549 "search-index",
550 LocalState,
551 NonIdempotent
552 ),
553 method_spec!("settings/get", "settings", ReadOnly, Idempotent),
554 method_spec!(
555 "settings/set_default_mode",
556 "settings",
557 LocalState,
558 NonIdempotent
559 ),
560 method_spec!(
561 "settings/set_file_backed_dynamic_context",
562 "settings",
563 LocalState,
564 NonIdempotent
565 ),
566 method_spec!(
567 "settings/set_search_index",
568 "settings",
569 LocalState,
570 NonIdempotent
571 ),
572 method_spec!("settings/set_shell", "settings", LocalState, NonIdempotent),
573 method_spec!(
574 "settings/set_web_search",
575 "settings",
576 LocalState,
577 NonIdempotent
578 ),
579 method_spec!("skills/list", "skills", ReadOnly, Idempotent),
580 method_spec!("skills/read", "skills", ReadOnly, Idempotent),
581 method_spec!("skills/setEnabled", "skills", LocalState, NonIdempotent),
582 method_spec!("skills/setExposure", "skills", LocalState, NonIdempotent),
583 method_spec!("speech/providers/list", "speech", ReadOnly, Idempotent),
584 method_spec!(
585 "speech/synthesis/providers/list",
586 "speech",
587 ReadOnly,
588 Idempotent
589 ),
590 method_spec!(
591 "speech/synthesize",
592 "speech",
593 ExternalProcess,
594 NonIdempotent
595 ),
596 method_spec!(
597 "speech/transcribe",
598 "speech",
599 ExternalProcess,
600 NonIdempotent
601 ),
602 method_spec!("stats/backfill", "stats", LocalState, NonIdempotent),
603 method_spec!("stats/export", "stats", LocalState, NonIdempotent),
604 method_spec!("stats/sessions", "stats", ReadOnly, Idempotent),
605 method_spec!("stats/summary", "stats", ReadOnly, Idempotent),
606 method_spec!("stats/tokens", "stats", ReadOnly, Idempotent),
607 method_spec!("stats/tools", "stats", ReadOnly, Idempotent),
608 method_spec!("tasks/cancel", "tasks", LocalState, NonIdempotent),
609 method_spec!("tasks/get", "tasks", ReadOnly, Idempotent),
610 method_spec!("tasks/list", "tasks", ReadOnly, Idempotent),
611 method_spec!("tasks/submit", "tasks", LocalState, NonIdempotent),
612 method_spec!(
613 "tasks/subscribe",
614 "tasks",
615 ReadOnly,
616 Idempotent,
617 [
618 "task.started",
619 "task.output",
620 "task.completed",
621 "task.failed",
622 "task.cancelled",
623 ]
624 ),
625 method_spec!("team/cleanup", "teams", LocalState, NonIdempotent),
626 method_spec!("team/list", "teams", ReadOnly, Idempotent),
627 method_spec!("team/member/focus", "teams", LocalState, NonIdempotent),
628 method_spec!("team/member/interrupt", "teams", LocalState, NonIdempotent),
629 method_spec!("team/member/message", "teams", LocalState, NonIdempotent),
630 method_spec!("team/member/start", "teams", LocalState, NonIdempotent),
631 method_spec!("team/pane/cleanup", "teams", LocalState, NonIdempotent),
632 method_spec!("team/pane/focus", "teams", LocalState, NonIdempotent),
633 method_spec!("team/read", "teams", ReadOnly, Idempotent),
634 method_spec!("team/start", "teams", LocalState, NonIdempotent),
635 method_spec!("thread/archive", "thread", LocalState, NonIdempotent),
636 method_spec!("thread/attach", "thread", LocalState, NonIdempotent),
637 method_spec!("thread/exit_plan", "thread", LocalState, NonIdempotent),
638 method_spec!("thread/fork", "thread", LocalState, NonIdempotent),
639 method_spec!("thread/fork_status", "thread", ReadOnly, Idempotent),
640 method_spec!(
641 "thread/goal/clear",
642 "thread",
643 LocalState,
644 NonIdempotent,
645 ["thread/goal/cleared"]
646 ),
647 method_spec!("thread/goal/get", "thread", ReadOnly, Idempotent),
648 method_spec!(
649 "thread/goal/set",
650 "thread",
651 LocalState,
652 NonIdempotent,
653 ["thread/goal/updated"]
654 ),
655 method_spec!(
656 "thread/compact",
657 "thread",
658 LocalState,
659 NonIdempotent,
660 ["context.compaction_started", "context.compaction_recorded"]
661 ),
662 method_spec!("thread/list", "thread", ReadOnly, Idempotent),
663 method_spec!("thread/read", "thread", ReadOnly, Idempotent),
664 method_spec!("thread/remove_fork", "thread", LocalState, NonIdempotent),
665 method_spec!(
666 "thread/resolve_approval",
667 "thread",
668 LocalState,
669 NonIdempotent
670 ),
671 method_spec!(
672 "thread/resolve_user_input",
673 "thread",
674 LocalState,
675 NonIdempotent
676 ),
677 method_spec!("thread/roadmap/open", "thread", LocalState, NonIdempotent),
678 method_spec!("thread/set_mode", "thread", LocalState, NonIdempotent),
679 method_spec!("thread/start", "thread", LocalState, NonIdempotent),
680 method_spec!("thread/state", "thread", ReadOnly, Idempotent),
681 method_spec!("tools/call", "tools", LocalState, NonIdempotent),
682 method_spec!("tools/list", "tools", ReadOnly, Idempotent),
683 method_spec!("tools/resolve", "tools", LocalState, NonIdempotent),
684 method_spec!("turn/interrupt", "turns", LocalState, NonIdempotent),
685 method_spec!("turn/start", "turns", LocalState, NonIdempotent),
686 method_spec!("turn/steer", "turns", LocalState, NonIdempotent),
687 method_spec!("turn/subagentTrace/read", "turns", ReadOnly, Idempotent),
688 method_spec!("turn/subagentTraces/list", "turns", ReadOnly, Idempotent),
689 method_spec!("vcs/changes/list", "vcs", ReadOnly, Idempotent),
690 method_spec!("vcs/changes/read", "vcs", ReadOnly, Idempotent),
691 method_spec!("vcs/lines/list", "vcs", ReadOnly, Idempotent),
692 method_spec!("vcs/lines/switch", "vcs", LocalState, NonIdempotent),
693 method_spec!("vcs/restore", "vcs", LocalState, NonIdempotent),
694 method_spec!("vcs/select", "vcs", LocalState, NonIdempotent),
695 method_spec!("vcs/snapshot/create", "vcs", LocalState, NonIdempotent),
696 method_spec!("vcs/status", "vcs", ReadOnly, Idempotent),
697 method_spec!("vcs/sync", "vcs", ExternalProcess, NonIdempotent),
698 method_spec!("webwright/artifacts", "webwright", ReadOnly, Idempotent),
699 method_spec!("webwright/export", "webwright", LocalState, NonIdempotent),
700 method_spec!("webwright/latestRun", "webwright", ReadOnly, Idempotent),
701 method_spec!("webwright/prepare", "webwright", LocalState, NonIdempotent),
702 method_spec!("webwright/report", "webwright", ReadOnly, Idempotent),
703 method_spec!(
704 "webwright/rerun",
705 "webwright",
706 ExternalProcess,
707 NonIdempotent
708 ),
709 method_spec!(
710 "webwright/setup",
711 "webwright",
712 ExternalProcess,
713 NonIdempotent
714 ),
715 method_spec!("webwright/submit", "webwright", LocalState, NonIdempotent),
716 method_spec!("webwright/verify", "webwright", ReadOnly, Idempotent),
717 method_spec!(
718 "webwright/visualJudge",
719 "webwright",
720 LocalState,
721 NonIdempotent
722 ),
723 method_spec!("workflow/enable", "workflow", LocalState, NonIdempotent),
724 method_spec!("workflow/ignore", "workflow", LocalState, NonIdempotent),
725 method_spec!("workflow/preview", "workflow", ReadOnly, Idempotent),
726 method_spec!("workflow/refresh", "workflow", LocalState, NonIdempotent),
727 method_spec!("workflow/remove", "workflow", LocalState, NonIdempotent),
728 method_spec!("workflow/scan", "workflow", ReadOnly, Idempotent),
729 method_spec!(
730 "workflows/approve",
731 "workflows",
732 LocalState,
733 NonIdempotent,
734 [
735 "workflows/approved",
736 "workflows/denied",
737 "workflows/queued",
738 "workflows/started",
739 ]
740 ),
741 method_spec!("workflows/get", "workflows", ReadOnly, Idempotent),
742 method_spec!("workflows/list", "workflows", ReadOnly, Idempotent),
743 method_spec!(
744 "workflows/pause",
745 "workflows",
746 LocalState,
747 NonIdempotent,
748 ["workflows/paused"]
749 ),
750 method_spec!(
751 "workflows/plan",
752 "workflows",
753 LocalState,
754 NonIdempotent,
755 ["workflows/drafted", "workflows/approvalRequested"]
756 ),
757 method_spec!(
758 "workflows/restartAgent",
759 "workflows",
760 LocalState,
761 NonIdempotent,
762 [
763 "workflows/agentQueued",
764 "workflows/agentStarted",
765 "workflows/agentCompleted",
766 "workflows/agentFailed",
767 ]
768 ),
769 method_spec!(
770 "workflows/resume",
771 "workflows",
772 LocalState,
773 NonIdempotent,
774 ["workflows/resumed"]
775 ),
776 method_spec!("workflows/save", "workflows", LocalState, NonIdempotent),
777 method_spec!(
778 "workflows/scripts/delete",
779 "workflows",
780 LocalState,
781 NonIdempotent
782 ),
783 method_spec!("workflows/scripts/list", "workflows", ReadOnly, Idempotent),
784 method_spec!("workflows/scripts/read", "workflows", ReadOnly, Idempotent),
785 method_spec!(
786 "workflows/stop",
787 "workflows",
788 LocalState,
789 NonIdempotent,
790 ["workflows/stopped"]
791 ),
792 method_spec!(
793 "workspace/changes/list",
794 "workspace",
795 ReadOnly,
796 Idempotent,
797 ["workspace/changeObserved"]
798 ),
799 method_spec!("workspace/create", "workspace", LocalState, NonIdempotent),
800 method_spec!(
801 "workspace/files/children",
802 "workspace-files",
803 ReadOnly,
804 Idempotent
805 ),
806 method_spec!(
807 "workspace/files/query",
808 "workspace-files",
809 ReadOnly,
810 Idempotent
811 ),
812 method_spec!(
813 "workspace/files/read",
814 "workspace-files",
815 ReadOnly,
816 Idempotent
817 ),
818 method_spec!(
819 "workspace/files/rebuild",
820 "workspace-files",
821 LocalState,
822 NonIdempotent,
823 ["workspace/files/statusChanged"]
824 ),
825 method_spec!(
826 "workspace/files/status",
827 "workspace-files",
828 ReadOnly,
829 Idempotent
830 ),
831 method_spec!("workspace/forget", "workspace", LocalState, NonIdempotent),
832 method_spec!("workspace/list", "workspace", ReadOnly, Idempotent),
833 method_spec!("workspace/update", "workspace", LocalState, NonIdempotent),
834];
835
836#[cfg(test)]
837mod tests {
838 use std::collections::BTreeSet;
839
840 use super::*;
841
842 #[test]
843 fn method_manifest_is_sorted_and_unique() {
844 let methods = app_server_method_specs();
845 let names = methods.iter().map(|spec| spec.method).collect::<Vec<_>>();
846 let mut sorted = names.clone();
847 sorted.sort_unstable();
848 assert_eq!(names, sorted);
849
850 let unique = names.iter().copied().collect::<BTreeSet<_>>();
851 assert_eq!(unique.len(), names.len());
852 }
853
854 #[test]
855 fn method_manifest_covers_broad_app_server_surface() {
856 let methods = app_server_method_specs()
857 .iter()
858 .map(|spec| spec.method)
859 .collect::<BTreeSet<_>>();
860 for required in [
861 "providers/list",
862 "settings/get",
863 "thread/start",
864 "turn/start",
865 "thread/resolve_approval",
866 "tools/call",
867 "commands/list",
868 "tasks/submit",
869 "webwright/prepare",
870 "team/member/message",
871 "plan/review/comment",
872 "hunk/rollback",
873 "workflow/scan",
874 "workflows/plan",
875 "marketplaces/search",
876 "plugins/install",
877 "packages/install",
878 "packages/list",
879 "media/list",
880 "memory/query",
881 "automations/list",
882 "processes/list",
883 "speech/providers/list",
884 "speech/synthesis/providers/list",
885 "speech/synthesize",
886 "speech/transcribe",
887 "vcs/status",
888 "vcs/select",
889 "workspace/files/children",
890 "workspace/files/query",
891 "workspace/files/read",
892 "workspace/files/rebuild",
893 "workspace/files/status",
894 ] {
895 assert!(methods.contains(required), "missing {required}");
896 }
897 assert!(!methods.contains("vcs/extras/list"));
898 }
899
900 #[test]
901 fn method_manifest_uses_canonical_vcs_type_names() {
902 let manifest = app_server_method_manifest();
903 let status = manifest
904 .methods
905 .iter()
906 .find(|method| method.method == "vcs/status")
907 .expect("vcs/status method");
908 assert_eq!(status.params_type, "VcsWorkspaceParams");
909 assert_eq!(status.result_type, "VcsStatus");
910
911 let select = manifest
912 .methods
913 .iter()
914 .find(|method| method.method == "vcs/select")
915 .expect("vcs/select method");
916 assert_eq!(select.params_type, "VcsSelectionParams");
917 assert_eq!(select.result_type, "VcsOperationResult");
918 }
919
920 #[test]
921 fn method_manifest_records_subscription_notifications() {
922 let methods = app_server_method_specs();
923 let processes = methods
924 .iter()
925 .find(|spec| spec.method == "processes/subscribe")
926 .expect("processes subscribe spec");
927 assert_eq!(processes.notifications, ["processes/changed"]);
928
929 let tasks = methods
930 .iter()
931 .find(|spec| spec.method == "tasks/subscribe")
932 .expect("tasks subscribe spec");
933 assert!(tasks.notifications.contains(&"task.started"));
934 assert!(tasks.notifications.contains(&"task.completed"));
935
936 let workflows_plan = methods
937 .iter()
938 .find(|spec| spec.method == "workflows/plan")
939 .expect("workflows plan spec");
940 assert!(workflows_plan.notifications.contains(&"workflows/drafted"));
941 assert!(
942 workflows_plan
943 .notifications
944 .contains(&"workflows/approvalRequested")
945 );
946
947 let workspace_files_rebuild = methods
948 .iter()
949 .find(|spec| spec.method == "workspace/files/rebuild")
950 .expect("workspace files rebuild spec");
951 assert_eq!(
952 workspace_files_rebuild.notifications,
953 ["workspace/files/statusChanged"]
954 );
955 }
956}