feat: surface codex app server governance summaries
This commit is contained in:
@@ -83,6 +83,22 @@ test("device detail exposes Codex App Server discovered model and extension summ
|
||||
{ name: "github", toolCount: 2, authStatus: "oAuth" },
|
||||
{ name: "figma", toolCount: 0, authStatus: "notLoggedIn" },
|
||||
],
|
||||
accountSummary: { signedIn: true, authMode: "chatgpt", planType: "pro", requiresOpenaiAuth: true },
|
||||
rateLimitSummary: { bucketCount: 2, maxUsedPercent: 42, reached: false },
|
||||
appConfigSummary: {
|
||||
appCount: 2,
|
||||
enabledAppCount: 1,
|
||||
defaultEnabled: true,
|
||||
destructiveEnabled: false,
|
||||
openWorldEnabled: false,
|
||||
},
|
||||
configRequirements: { managed: true, requirementCount: 2, warningCount: 1 },
|
||||
externalAgentMigration: {
|
||||
itemCount: 3,
|
||||
homeItemCount: 1,
|
||||
projectItemCount: 2,
|
||||
itemTypes: ["AGENTS_MD", "MCP_SERVER_CONFIG", "SKILLS"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -95,6 +111,8 @@ test("device detail exposes Codex App Server discovered model and extension summ
|
||||
assert.equal(cards.capabilities.items.codexModels, "模型:2 个 · 默认 gpt-5.4 · 快速 gpt-5.4-mini · 深度 gpt-5.4");
|
||||
assert.equal(cards.capabilities.items.codexExtensions, "扩展:Skill 1 个 · Plugin 1 个 · App 1 个");
|
||||
assert.equal(cards.capabilities.items.codexGovernance, "治理:实验特性 2 个 · 协作模式 2 个 · MCP 2 个 · 权限 1 个");
|
||||
assert.equal(cards.capabilities.items.codexAccount, "账号:chatgpt · 套餐 pro · 额度 42%");
|
||||
assert.equal(cards.capabilities.items.codexConfig, "配置:App 2 个 · 已启用 1 个 · 托管要求 2 个 · 外部迁移 3 项");
|
||||
});
|
||||
|
||||
test("device detail exposes folder and project conflict skeleton from workspace policy", async () => {
|
||||
|
||||
@@ -63,6 +63,11 @@ test("device heartbeat preserves Codex App Server capability metadata", async ()
|
||||
collaborationModes: [{ id: "plan" }],
|
||||
permissionProfiles: [{ id: ":workspace" }],
|
||||
mcpServers: [{ name: "github", toolCount: 2, authStatus: "oAuth" }],
|
||||
accountSummary: { signedIn: true, authMode: "chatgpt", planType: "pro", requiresOpenaiAuth: true },
|
||||
rateLimitSummary: { bucketCount: 2, maxUsedPercent: 42, reached: false },
|
||||
appConfigSummary: { appCount: 2, enabledAppCount: 1 },
|
||||
configRequirements: { managed: true, requirementCount: 2, warningCount: 1 },
|
||||
externalAgentMigration: { itemCount: 3, homeItemCount: 1, projectItemCount: 2 },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -85,4 +90,20 @@ test("device heartbeat preserves Codex App Server capability metadata", async ()
|
||||
?.toolCount,
|
||||
2,
|
||||
);
|
||||
assert.equal(
|
||||
(
|
||||
updatedDevice?.capabilities?.codexAppServer.metadata?.accountSummary as
|
||||
| { authMode?: string; planType?: string }
|
||||
| undefined
|
||||
)?.authMode,
|
||||
"chatgpt",
|
||||
);
|
||||
assert.equal(
|
||||
(
|
||||
updatedDevice?.capabilities?.codexAppServer.metadata?.externalAgentMigration as
|
||||
| { itemCount?: number }
|
||||
| undefined
|
||||
)?.itemCount,
|
||||
3,
|
||||
);
|
||||
});
|
||||
|
||||
115
tests/fixtures/codex-app-server-runtime.mjs
vendored
115
tests/fixtures/codex-app-server-runtime.mjs
vendored
@@ -266,6 +266,121 @@ rl.on("line", (line) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "account/read") {
|
||||
send({
|
||||
id: message.id,
|
||||
result: {
|
||||
account: {
|
||||
type: "chatgpt",
|
||||
email: "private-user@example.com",
|
||||
planType: "pro",
|
||||
accessToken: "sk-secret-should-not-leak",
|
||||
},
|
||||
requiresOpenaiAuth: true,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "account/rateLimits/read") {
|
||||
send({
|
||||
id: message.id,
|
||||
result: {
|
||||
rateLimits: {
|
||||
limitId: "codex",
|
||||
limitName: "Primary Codex",
|
||||
primary: { usedPercent: 25, windowDurationMins: 15, resetsAt: 1730947200 },
|
||||
secondary: null,
|
||||
rateLimitReachedType: null,
|
||||
},
|
||||
rateLimitsByLimitId: {
|
||||
codex: {
|
||||
limitId: "codex",
|
||||
primary: { usedPercent: 25, windowDurationMins: 15, resetsAt: 1730947200 },
|
||||
rateLimitReachedType: null,
|
||||
},
|
||||
codex_other: {
|
||||
limitId: "codex_other",
|
||||
limitName: "codex_other",
|
||||
primary: { usedPercent: 42, windowDurationMins: 60, resetsAt: 1730950800 },
|
||||
rateLimitReachedType: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "config/read") {
|
||||
send({
|
||||
id: message.id,
|
||||
result: {
|
||||
config: {
|
||||
api_key: "sk-secret-should-not-leak",
|
||||
model: "gpt-5.4",
|
||||
apps: {
|
||||
_default: {
|
||||
enabled: true,
|
||||
destructive_enabled: false,
|
||||
open_world_enabled: false,
|
||||
},
|
||||
google_drive: {
|
||||
enabled: true,
|
||||
destructive_enabled: false,
|
||||
default_tools_approval_mode: "prompt",
|
||||
},
|
||||
secret_app: {
|
||||
enabled: false,
|
||||
token: "sk-secret-should-not-leak",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "configRequirements/read") {
|
||||
send({
|
||||
id: message.id,
|
||||
result: {
|
||||
managed: true,
|
||||
requirements: [
|
||||
{ keyPath: "apps._default.destructive_enabled", status: "blocked", sourcePath: "/Users/kris/.codex/config.toml" },
|
||||
{ keyPath: "sandbox_mode", status: "ok" },
|
||||
],
|
||||
warnings: [{ message: "policy reads /Users/kris/.ssh/id_ed25519" }],
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "externalAgentConfig/detect") {
|
||||
send({
|
||||
id: message.id,
|
||||
result: {
|
||||
items: [
|
||||
{
|
||||
itemType: "AGENTS_MD",
|
||||
description: "Import /Users/kris/code/boss/CLAUDE.md to /Users/kris/code/boss/AGENTS.md.",
|
||||
cwd: "/Users/kris/code/boss",
|
||||
},
|
||||
{
|
||||
itemType: "SKILLS",
|
||||
description: "Copy skill folders from /Users/kris/.claude/skills to /Users/kris/.agents/skills.",
|
||||
cwd: null,
|
||||
},
|
||||
{
|
||||
itemType: "MCP_SERVER_CONFIG",
|
||||
description: "Migrate server config with token sk-secret-should-not-leak",
|
||||
cwd: "/Users/kris/code/boss",
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "thread/resume") {
|
||||
send({
|
||||
id: message.id,
|
||||
|
||||
@@ -36,6 +36,33 @@ test("codex app-server discovery includes governance and MCP summaries without l
|
||||
assert.equal(metadata.mcpServers[0].name, "github");
|
||||
assert.equal(metadata.mcpServers[0].toolCount, 2);
|
||||
assert.equal(metadata.mcpServers[0].authStatus, "oAuth");
|
||||
assert.deepEqual(metadata.accountSummary, {
|
||||
signedIn: true,
|
||||
authMode: "chatgpt",
|
||||
planType: "pro",
|
||||
requiresOpenaiAuth: true,
|
||||
});
|
||||
assert.equal(metadata.rateLimitSummary.bucketCount, 2);
|
||||
assert.equal(metadata.rateLimitSummary.maxUsedPercent, 42);
|
||||
assert.equal(metadata.rateLimitSummary.reached, false);
|
||||
assert.deepEqual(metadata.appConfigSummary, {
|
||||
appCount: 2,
|
||||
enabledAppCount: 1,
|
||||
defaultEnabled: true,
|
||||
destructiveEnabled: false,
|
||||
openWorldEnabled: false,
|
||||
});
|
||||
assert.deepEqual(metadata.configRequirements, {
|
||||
managed: true,
|
||||
requirementCount: 2,
|
||||
warningCount: 1,
|
||||
});
|
||||
assert.deepEqual(metadata.externalAgentMigration, {
|
||||
itemCount: 3,
|
||||
homeItemCount: 1,
|
||||
projectItemCount: 2,
|
||||
itemTypes: ["AGENTS_MD", "MCP_SERVER_CONFIG", "SKILLS"],
|
||||
});
|
||||
|
||||
const serialized = JSON.stringify(metadata);
|
||||
assert.equal(serialized.includes("sk-secret-should-not-leak"), false);
|
||||
@@ -43,6 +70,9 @@ test("codex app-server discovery includes governance and MCP summaries without l
|
||||
assert.equal(serialized.includes("id_ed25519"), false);
|
||||
assert.equal(serialized.includes("filesystem"), false);
|
||||
assert.equal(serialized.includes("resources"), false);
|
||||
assert.equal(serialized.includes("private-user@example.com"), false);
|
||||
assert.equal(serialized.includes("CLAUDE.md"), false);
|
||||
assert.equal(serialized.includes("AGENTS.md"), false);
|
||||
});
|
||||
|
||||
function encodeWsTextFrame(value) {
|
||||
|
||||
Reference in New Issue
Block a user