feat: surface codex app server thread visibility
This commit is contained in:
@@ -99,6 +99,25 @@ test("device detail exposes Codex App Server discovered model and extension summ
|
||||
projectItemCount: 2,
|
||||
itemTypes: ["AGENTS_MD", "MCP_SERVER_CONFIG", "SKILLS"],
|
||||
},
|
||||
threadSummary: {
|
||||
threadCount: 3,
|
||||
loadedThreadCount: 2,
|
||||
activeThreadCount: 1,
|
||||
archivedThreadCount: 1,
|
||||
latestUpdatedAt: "2026-06-03T08:20:00.000Z",
|
||||
sourceKinds: ["app", "cli"],
|
||||
visibleThreads: [
|
||||
{
|
||||
id: "thr-active",
|
||||
name: "Boss App Server rollout",
|
||||
sourceKind: "app",
|
||||
status: "active",
|
||||
archived: false,
|
||||
loaded: true,
|
||||
updatedAt: "2026-06-03T08:20:00.000Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -113,6 +132,7 @@ test("device detail exposes Codex App Server discovered model and extension summ
|
||||
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 项");
|
||||
assert.equal(cards.capabilities.items.codexThreads, "线程:3 个 · 已加载 2 个 · 活跃 1 个 · 最新 2026-06-03 16:20");
|
||||
});
|
||||
|
||||
test("device detail exposes folder and project conflict skeleton from workspace policy", async () => {
|
||||
|
||||
@@ -68,6 +68,13 @@ test("device heartbeat preserves Codex App Server capability metadata", async ()
|
||||
appConfigSummary: { appCount: 2, enabledAppCount: 1 },
|
||||
configRequirements: { managed: true, requirementCount: 2, warningCount: 1 },
|
||||
externalAgentMigration: { itemCount: 3, homeItemCount: 1, projectItemCount: 2 },
|
||||
threadSummary: {
|
||||
threadCount: 3,
|
||||
loadedThreadCount: 2,
|
||||
activeThreadCount: 1,
|
||||
latestUpdatedAt: "2026-06-03T08:20:00.000Z",
|
||||
visibleThreads: [{ id: "thr-active", name: "Boss App Server rollout", loaded: true }],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -106,4 +113,20 @@ test("device heartbeat preserves Codex App Server capability metadata", async ()
|
||||
)?.itemCount,
|
||||
3,
|
||||
);
|
||||
assert.equal(
|
||||
(
|
||||
updatedDevice?.capabilities?.codexAppServer.metadata?.threadSummary as
|
||||
| { threadCount?: number; visibleThreads?: Array<{ id?: string }> }
|
||||
| undefined
|
||||
)?.threadCount,
|
||||
3,
|
||||
);
|
||||
assert.equal(
|
||||
(
|
||||
updatedDevice?.capabilities?.codexAppServer.metadata?.threadSummary as
|
||||
| { visibleThreads?: Array<{ id?: string }> }
|
||||
| undefined
|
||||
)?.visibleThreads?.[0]?.id,
|
||||
"thr-active",
|
||||
);
|
||||
});
|
||||
|
||||
50
tests/fixtures/codex-app-server-runtime.mjs
vendored
50
tests/fixtures/codex-app-server-runtime.mjs
vendored
@@ -381,6 +381,56 @@ rl.on("line", (line) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "thread/list") {
|
||||
send({
|
||||
id: message.id,
|
||||
result: {
|
||||
data: [
|
||||
{
|
||||
id: "thr-active",
|
||||
name: "Boss App Server rollout",
|
||||
sourceKind: "app",
|
||||
archived: false,
|
||||
updatedAt: "2026-06-03T08:20:00.000Z",
|
||||
cwd: "/Users/kris/code/boss",
|
||||
status: { type: "active", activeFlags: ["running"] },
|
||||
turns: [{ userInput: "secret user text should not leak" }],
|
||||
},
|
||||
{
|
||||
id: "thr-idle",
|
||||
name: "AItoukui planning",
|
||||
sourceKind: "cli",
|
||||
archived: false,
|
||||
updatedAt: "2026-06-03T07:00:00.000Z",
|
||||
cwd: "/Users/kris/code/AItoukui",
|
||||
status: { type: "idle" },
|
||||
},
|
||||
{
|
||||
id: "thr-archived",
|
||||
name: "Old private thread",
|
||||
sourceKind: "app",
|
||||
archived: true,
|
||||
updatedAt: "2026-06-01T01:00:00.000Z",
|
||||
cwd: "/Users/kris/private",
|
||||
status: { type: "notLoaded" },
|
||||
},
|
||||
],
|
||||
nextCursor: null,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "thread/loaded/list") {
|
||||
send({
|
||||
id: message.id,
|
||||
result: {
|
||||
threadIds: ["thr-active", "thr-idle"],
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.method === "thread/resume") {
|
||||
send({
|
||||
id: message.id,
|
||||
|
||||
@@ -63,6 +63,21 @@ test("codex app-server discovery includes governance and MCP summaries without l
|
||||
projectItemCount: 2,
|
||||
itemTypes: ["AGENTS_MD", "MCP_SERVER_CONFIG", "SKILLS"],
|
||||
});
|
||||
assert.equal(metadata.threadSummary.threadCount, 3);
|
||||
assert.equal(metadata.threadSummary.loadedThreadCount, 2);
|
||||
assert.equal(metadata.threadSummary.activeThreadCount, 1);
|
||||
assert.equal(metadata.threadSummary.archivedThreadCount, 1);
|
||||
assert.equal(metadata.threadSummary.latestUpdatedAt, "2026-06-03T08:20:00.000Z");
|
||||
assert.deepEqual(metadata.threadSummary.sourceKinds, ["app", "cli"]);
|
||||
assert.deepEqual(metadata.threadSummary.visibleThreads[0], {
|
||||
id: "thr-active",
|
||||
name: "Boss App Server rollout",
|
||||
sourceKind: "app",
|
||||
status: "active",
|
||||
archived: false,
|
||||
loaded: true,
|
||||
updatedAt: "2026-06-03T08:20:00.000Z",
|
||||
});
|
||||
|
||||
const serialized = JSON.stringify(metadata);
|
||||
assert.equal(serialized.includes("sk-secret-should-not-leak"), false);
|
||||
@@ -73,6 +88,8 @@ test("codex app-server discovery includes governance and MCP summaries without l
|
||||
assert.equal(serialized.includes("private-user@example.com"), false);
|
||||
assert.equal(serialized.includes("CLAUDE.md"), false);
|
||||
assert.equal(serialized.includes("AGENTS.md"), false);
|
||||
assert.equal(serialized.includes("secret user text should not leak"), false);
|
||||
assert.equal(serialized.includes("Old private thread"), false);
|
||||
});
|
||||
|
||||
function encodeWsTextFrame(value) {
|
||||
|
||||
Reference in New Issue
Block a user