Skip to content

Commit 0a856b6

Browse files
committed
feat: expose needs_auth for plugin/read.
1 parent fe287ac commit 0a856b6

File tree

10 files changed

+391
-9
lines changed

10 files changed

+391
-9
lines changed

codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5232,11 +5232,15 @@
52325232
},
52335233
"name": {
52345234
"type": "string"
5235+
},
5236+
"needsAuth": {
5237+
"type": "boolean"
52355238
}
52365239
},
52375240
"required": [
52385241
"id",
5239-
"name"
5242+
"name",
5243+
"needsAuth"
52405244
],
52415245
"type": "object"
52425246
},

codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,11 +492,15 @@
492492
},
493493
"name": {
494494
"type": "string"
495+
},
496+
"needsAuth": {
497+
"type": "boolean"
495498
}
496499
},
497500
"required": [
498501
"id",
499-
"name"
502+
"name",
503+
"needsAuth"
500504
],
501505
"type": "object"
502506
},

codex-rs/app-server-protocol/schema/json/v2/PluginInstallResponse.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@
2121
},
2222
"name": {
2323
"type": "string"
24+
},
25+
"needsAuth": {
26+
"type": "boolean"
2427
}
2528
},
2629
"required": [
2730
"id",
28-
"name"
31+
"name",
32+
"needsAuth"
2933
],
3034
"type": "object"
3135
},

codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@
2525
},
2626
"name": {
2727
"type": "string"
28+
},
29+
"needsAuth": {
30+
"type": "boolean"
2831
}
2932
},
3033
"required": [
3134
"id",
32-
"name"
35+
"name",
36+
"needsAuth"
3337
],
3438
"type": "object"
3539
},

codex-rs/app-server-protocol/schema/typescript/v2/AppSummary.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
/**
66
* EXPERIMENTAL - app metadata summary for plugin responses.
77
*/
8-
export type AppSummary = { id: string, name: string, description: string | null, installUrl: string | null, };
8+
export type AppSummary = { id: string, name: string, description: string | null, installUrl: string | null, needsAuth: boolean, };

codex-rs/app-server-protocol/src/protocol/v2.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,6 +2035,7 @@ pub struct AppSummary {
20352035
pub name: String,
20362036
pub description: Option<String>,
20372037
pub install_url: Option<String>,
2038+
pub needs_auth: bool,
20382039
}
20392040

20402041
impl From<AppInfo> for AppSummary {
@@ -2044,6 +2045,7 @@ impl From<AppInfo> for AppSummary {
20442045
name: value.name,
20452046
description: value.description,
20462047
install_url: value.install_url,
2048+
needs_auth: false,
20472049
}
20482050
}
20492051
}

codex-rs/app-server/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ Example with notification opt-out:
164164
- `collaborationMode/list` — list available collaboration mode presets (experimental, no pagination). This response omits built-in developer instructions; clients should either pass `settings.developer_instructions: null` when setting a mode to use Codex's built-in instructions, or provide their own instructions explicitly.
165165
- `skills/list` — list skills for one or more `cwd` values (optional `forceReload`).
166166
- `plugin/list` — list discovered plugin marketplaces and plugin state, including effective marketplace install/auth policy metadata and best-effort `featuredPluginIds` for the official curated marketplace. `interface.category` uses the marketplace category when present; otherwise it falls back to the plugin manifest category. Pass `forceRemoteSync: true` to refresh curated plugin state before listing (**under development; do not call from production clients yet**).
167-
- `plugin/read` — read one plugin by `marketplacePath` plus `pluginName`, returning marketplace info, a list-style `summary`, manifest descriptions/interface metadata, and bundled skills/apps/MCP server names (**under development; do not call from production clients yet**).
167+
- `plugin/read` — read one plugin by `marketplacePath` plus `pluginName`, returning marketplace info, a list-style `summary`, manifest descriptions/interface metadata, and bundled skills/apps/MCP server names. Plugin app summaries also include `needsAuth` when the server can determine connector accessibility (**under development; do not call from production clients yet**).
168168
- `skills/changed` — notification emitted when watched local skill files change.
169169
- `app/list` — list available apps.
170170
- `skills/config/write` — write user-level skill config by path.

codex-rs/app-server/src/codex_message_processor/plugin_app_helpers.rs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,47 @@ pub(super) async fn load_plugin_app_summaries(
2626
}
2727
};
2828

29-
connectors::connectors_for_plugin_apps(connectors, plugin_apps)
29+
let plugin_connectors = connectors::connectors_for_plugin_apps(connectors, plugin_apps);
30+
31+
let accessible_connectors =
32+
match connectors::list_accessible_connectors_from_mcp_tools_with_options_and_status(
33+
config, /*force_refetch*/ false,
34+
)
35+
.await
36+
{
37+
Ok(status) if status.codex_apps_ready => status.connectors,
38+
Ok(_) => {
39+
return plugin_connectors
40+
.into_iter()
41+
.map(AppSummary::from)
42+
.collect();
43+
}
44+
Err(err) => {
45+
warn!("failed to load app auth state for plugin/read: {err:#}");
46+
return plugin_connectors
47+
.into_iter()
48+
.map(AppSummary::from)
49+
.collect();
50+
}
51+
};
52+
53+
let accessible_ids = accessible_connectors
54+
.iter()
55+
.map(|connector| connector.id.as_str())
56+
.collect::<HashSet<_>>();
57+
58+
plugin_connectors
3059
.into_iter()
31-
.map(AppSummary::from)
60+
.map(|connector| {
61+
let needs_auth = !accessible_ids.contains(connector.id.as_str());
62+
AppSummary {
63+
id: connector.id,
64+
name: connector.name,
65+
description: connector.description,
66+
install_url: connector.install_url,
67+
needs_auth,
68+
}
69+
})
3270
.collect()
3371
}
3472

@@ -58,7 +96,13 @@ pub(super) fn plugin_apps_needing_auth(
5896
&& !accessible_ids.contains(connector.id.as_str())
5997
})
6098
.cloned()
61-
.map(AppSummary::from)
99+
.map(|connector| AppSummary {
100+
id: connector.id,
101+
name: connector.name,
102+
description: connector.description,
103+
install_url: connector.install_url,
104+
needs_auth: true,
105+
})
62106
.collect()
63107
}
64108

codex-rs/app-server/tests/suite/v2/plugin_install.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ async fn plugin_install_returns_apps_needing_auth() -> Result<()> {
435435
name: "Alpha".to_string(),
436436
description: Some("Alpha connector".to_string()),
437437
install_url: Some("https://chatgpt.com/apps/alpha/alpha".to_string()),
438+
needs_auth: true,
438439
}],
439440
}
440441
);
@@ -518,6 +519,7 @@ async fn plugin_install_filters_disallowed_apps_needing_auth() -> Result<()> {
518519
name: "Alpha".to_string(),
519520
description: Some("Alpha connector".to_string()),
520521
install_url: Some("https://chatgpt.com/apps/alpha/alpha".to_string()),
522+
needs_auth: true,
521523
}],
522524
}
523525
);

0 commit comments

Comments
 (0)