feat: expand codex app server discovery

This commit is contained in:
AI Bot
2026-06-02 23:11:21 +08:00
parent 94e0cc8bad
commit 88b028ad2b
11 changed files with 295 additions and 12 deletions

View File

@@ -1214,6 +1214,79 @@ function normalizeDiscoveryApps(result) {
.filter(Boolean);
}
function normalizeDiscoveryExperimentalFeatures(result) {
return asArray(result?.data)
.map((feature) => {
const name = trimToDefined(feature?.name);
if (!name) return null;
return {
name,
stage: safeProgressText(feature?.stage, 48) || "unknown",
displayName: trimToDefined(feature?.displayName) || name,
enabled: Boolean(feature?.enabled),
defaultEnabled: Boolean(feature?.defaultEnabled),
};
})
.filter(Boolean);
}
function normalizeDiscoveryCollaborationModes(result) {
const modes = Array.isArray(result)
? result
: asArray(result?.data).length > 0
? asArray(result?.data)
: asArray(result?.modes ?? result?.collaborationModes);
return modes
.map((mode) => {
const id =
trimToDefined(mode?.id) ||
trimToDefined(mode?.name) ||
trimToDefined(mode?.mode) ||
(typeof mode === "string" ? trimToDefined(mode) : undefined);
if (!id) return null;
return {
id,
name: trimToDefined(mode?.name) || id,
displayName: trimToDefined(mode?.displayName) || trimToDefined(mode?.title) || id,
description: safeRuntimeDiagnosticText(mode?.description, 160),
};
})
.filter(Boolean);
}
function normalizeDiscoveryPermissionProfiles(result) {
return asArray(result?.data)
.map((profile) => {
const id = trimToDefined(profile?.id) || trimToDefined(profile?.name);
if (!id) return null;
return {
id,
description: safeRuntimeDiagnosticText(profile?.description, 160),
};
})
.filter(Boolean);
}
function normalizeDiscoveryMcpServers(result) {
return asArray(result?.data)
.map((server) => {
const name = trimToDefined(server?.name);
if (!name) return null;
const toolCount =
server?.tools && typeof server.tools === "object" && !Array.isArray(server.tools)
? Object.keys(server.tools).length
: asArray(server?.tools).length;
return {
name,
authStatus: safeProgressText(server?.authStatus, 64) || "unknown",
toolCount,
resourceCount: asArray(server?.resources).length,
resourceTemplateCount: asArray(server?.resourceTemplates).length,
};
})
.filter(Boolean);
}
async function withCodexAppServerRpcSession(runnerConfig, callback) {
const cwd = runnerConfig.cwd || process.cwd();
let closed = false;
@@ -1293,6 +1366,9 @@ async function withCodexAppServerRpcSession(runnerConfig, callback) {
title: runnerConfig.clientTitle,
version: runnerConfig.clientVersion,
},
capabilities: {
experimentalApi: true,
},
});
notify("initialized", {});
return await callback(request);
@@ -1316,12 +1392,27 @@ export async function discoverCodexAppServerCapabilities(runnerConfig) {
return withCodexAppServerRpcSession(runnerConfig, async (request) => {
const limit = runnerConfig.discoveryLimit ?? 20;
const [modelResult, providerCapabilities, skillsResult, pluginResult, appsResult] = await Promise.all([
const cwd = runnerConfig.cwd || process.cwd();
const [
modelResult,
providerCapabilities,
skillsResult,
pluginResult,
appsResult,
experimentalFeaturesResult,
collaborationModesResult,
permissionProfilesResult,
mcpServersResult,
] = await Promise.all([
safeRequest(request, "model/list", { includeHidden: false, limit }),
safeRequest(request, "modelProvider/capabilities/read", {}),
safeRequest(request, "skills/list", { cwds: [runnerConfig.cwd || process.cwd()], forceReload: false }),
safeRequest(request, "plugin/list", { cwds: [runnerConfig.cwd || process.cwd()] }),
safeRequest(request, "skills/list", { cwds: [cwd], forceReload: false }),
safeRequest(request, "plugin/list", { cwds: [cwd] }),
safeRequest(request, "app/list", { limit }),
safeRequest(request, "experimentalFeature/list", { limit }),
safeRequest(request, "collaborationMode/list", {}),
safeRequest(request, "permissionProfile/list", { cwd, limit }),
safeRequest(request, "mcpServerStatus/list", { limit, detail: "toolsAndAuthOnly" }),
]);
const models = asArray(modelResult?.data)
@@ -1346,14 +1437,30 @@ export async function discoverCodexAppServerCapabilities(runnerConfig) {
skills: normalizeDiscoverySkills(skillsResult).slice(0, limit),
plugins: normalizeDiscoveryPlugins(pluginResult).slice(0, limit),
apps: normalizeDiscoveryApps(appsResult).slice(0, limit),
experimentalFeatures: normalizeDiscoveryExperimentalFeatures(experimentalFeaturesResult).slice(0, limit),
collaborationModes: normalizeDiscoveryCollaborationModes(collaborationModesResult).slice(0, limit),
permissionProfiles: normalizeDiscoveryPermissionProfiles(permissionProfilesResult).slice(0, limit),
mcpServers: normalizeDiscoveryMcpServers(mcpServersResult).slice(0, limit),
errors: [
modelResult?.__bossError ? `model/list:${modelResult.__bossError}` : undefined,
modelResult?.__bossError ? `model/list:${safeRuntimeDiagnosticText(modelResult.__bossError)}` : undefined,
providerCapabilities?.__bossError
? `modelProvider/capabilities/read:${providerCapabilities.__bossError}`
? `modelProvider/capabilities/read:${safeRuntimeDiagnosticText(providerCapabilities.__bossError)}`
: undefined,
skillsResult?.__bossError ? `skills/list:${safeRuntimeDiagnosticText(skillsResult.__bossError)}` : undefined,
pluginResult?.__bossError ? `plugin/list:${safeRuntimeDiagnosticText(pluginResult.__bossError)}` : undefined,
appsResult?.__bossError ? `app/list:${safeRuntimeDiagnosticText(appsResult.__bossError)}` : undefined,
experimentalFeaturesResult?.__bossError
? `experimentalFeature/list:${safeRuntimeDiagnosticText(experimentalFeaturesResult.__bossError)}`
: undefined,
collaborationModesResult?.__bossError
? `collaborationMode/list:${safeRuntimeDiagnosticText(collaborationModesResult.__bossError)}`
: undefined,
permissionProfilesResult?.__bossError
? `permissionProfile/list:${safeRuntimeDiagnosticText(permissionProfilesResult.__bossError)}`
: undefined,
mcpServersResult?.__bossError
? `mcpServerStatus/list:${safeRuntimeDiagnosticText(mcpServersResult.__bossError)}`
: undefined,
skillsResult?.__bossError ? `skills/list:${skillsResult.__bossError}` : undefined,
pluginResult?.__bossError ? `plugin/list:${pluginResult.__bossError}` : undefined,
appsResult?.__bossError ? `app/list:${appsResult.__bossError}` : undefined,
].filter(Boolean),
};
});