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