Files
pikasTech-HWLAB/web/hwlab-cloud-web/code-agent-status.test.ts
T

604 lines
21 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import test from "node:test";
import { classifyCodeAgentStatusSummary } from "./code-agent-status.ts";
const liveRevision = Object.freeze({
healthLive: {
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "ok",
commitId: "7de6edd2c41f54e4265e822d2593fa67057fa41a"
}
}
});
test("summarizes long-lived Code Agent as green with current deployment revision only", () => {
const summary = classifyCodeAgentStatusSummary({
live: liveRevision,
availability: {
status: "codex-stdio-feasible",
ready: true,
provider: "codex-stdio",
mode: "codex-stdio",
backend: "hwlab-cloud-api/codex-stdio",
capabilityLevel: "long-lived-codex-stdio-session",
sessionMode: "codex-app-server-stdio-long-lived",
implementationType: "repo-owned-codex-app-server-stdio-session",
session: {
status: "idle",
lastTraceId: "trc_ready"
},
runner: {
kind: "codex-app-server-stdio-runner",
codexStdio: true
},
longLivedSessionGate: {
status: "pass"
},
codexStdioFeasibility: {
canStartLongLivedCodexStdio: true
},
providerTrace: {
protocol: "codex-app-server-jsonrpc-stdio",
command: "codex app-server --listen stdio://",
terminalStatus: "completed",
wireApi: "responses"
}
}
});
assert.equal(summary.kind, "long-lived-session");
assert.equal(summary.label, "长会话可用");
assert.equal(summary.tone, "ok");
assert.equal(summary.codeAgentStatus, "codex-stdio-feasible");
assert.equal(summary.providerModeBackend, "codex-stdio / codex-stdio / hwlab-cloud-api/codex-stdio");
assert.equal(summary.capabilityLevel, "long-lived-codex-stdio-session");
assert.equal(summary.sessionSummary, "codex-app-server-stdio-long-lived / idle / idle");
assert.equal(summary.sessionLifecycleStatus, "idle");
assert.match(summary.sessionLifecycleHint, /新会话已建立/u);
assert.equal(summary.runnerKind, "codex-app-server-stdio-runner");
assert.equal(summary.protocol, "codex-app-server-jsonrpc-stdio");
assert.equal(summary.implementationType, "repo-owned-codex-app-server-stdio-session");
assert.equal(summary.providerTraceCommand, "codex app-server --listen stdio://");
assert.equal(summary.providerTraceTerminalStatus, "completed");
assert.match(summary.runtimePathLabel, /repo-owned Codex app-server stdio/u);
assert.equal(summary.readinessBlockers.length, 0);
assert.equal(summary.lastTraceId, "trc_ready");
assert.equal(summary.deploymentRevision, "7de6edd2c41f");
assert.equal(Object.keys(summary.fields).includes("sourceMain"), false);
});
test("summarizes Codex app-server stdio thread as reusable long-lived session", () => {
const summary = classifyCodeAgentStatusSummary({
latestMessage: {
status: "completed",
provider: "codex-stdio",
mode: "codex-stdio",
backend: "hwlab-cloud-api/codex-app-server-stdio",
capabilityLevel: "long-lived-codex-stdio-session",
sessionMode: "codex-app-server-stdio-long-lived",
implementationType: "repo-owned-codex-app-server-stdio-session",
session: {
sessionId: "ses_app_server",
threadId: "thread_app_server",
status: "idle",
lastTraceId: "trc_app_server",
codexStdio: true
},
sessionReuse: {
sessionId: "ses_app_server",
threadId: "thread_app_server",
reused: true,
turn: 2
},
runner: {
kind: "codex-app-server-stdio-runner",
codexStdio: true,
writeCapable: true,
durableSession: true
},
longLivedSessionGate: {
status: "pass"
},
providerTrace: {
protocol: "codex-app-server-jsonrpc-stdio",
threadId: "thread_app_server",
terminalStatus: "completed"
}
}
});
assert.equal(summary.kind, "long-lived-session");
assert.equal(summary.tone, "ok");
assert.equal(summary.sessionIdStatus, "ses_app_server / thread_app_server / idle / idle");
assert.equal(summary.sessionLifecycleLabel, "继续当前会话");
assert.match(summary.sessionLifecycleHint, /可继续当前会话/u);
assert.equal(summary.fields.threadId, "thread_app_server");
});
test("summarizes AgentRun invalid tool-call JSON as provider-side blocked status", () => {
const summary = classifyCodeAgentStatusSummary({
latestMessage: {
status: "failed",
provider: "codex-stdio",
backend: "hwlab-cloud-api/codex-app-server-stdio",
capabilityLevel: "long-lived-codex-stdio-session",
sessionMode: "codex-app-server-stdio-long-lived",
implementationType: "repo-owned-codex-app-server-stdio-session",
runner: { kind: "codex-app-server-stdio-runner" },
providerTrace: {
protocol: "codex-app-server-jsonrpc-stdio",
command: "codex app-server --listen stdio://",
terminalStatus: "failed",
failureKind: "provider-invalid-tool-call",
failureMessage: "invalid params, invalid function arguments json string, tool_call_id: call_function_selftest_2 (2013)"
},
error: {
code: "provider-invalid-tool-call",
category: "provider_invalid_tool_call"
},
traceId: "trc_status_invalid_tool_call"
}
});
assert.equal(summary.kind, "blocked");
assert.equal(summary.tone, "blocked");
assert.equal(summary.providerTraceFailureKind, "provider-invalid-tool-call");
assert.equal(summary.runtimePathLabel, "BLOCKEDCodex tool-call JSON 无效");
assert.match(summary.runtimePathSummary, /不是 HWLAB device-pod/u);
});
test("maps degraded readonly session tools to warning, not green", () => {
const summary = classifyCodeAgentStatusSummary({
availability: {
status: "partial",
ready: false,
provider: "codex-readonly-runner",
backend: "hwlab-cloud-api/controlled-readonly-session-registry",
capabilityLevel: "read-only-session-tools",
sessionMode: "controlled-readonly-session-registry",
workspace: "/workspace/hwlab",
sandbox: "read-only",
session: {
sessionId: "ses_readonly",
status: "idle",
lastTraceId: "trc_readonly",
workspace: "/workspace/hwlab",
sandbox: "read-only",
runnerKind: "hwlab-readonly-runner",
sessionMode: "controlled-readonly-session-registry"
},
runner: {
kind: "hwlab-readonly-runner",
writeCapable: false
},
toolCalls: [{ name: "pwd", status: "completed" }],
skills: { status: "not_requested", count: 0 },
runnerTrace: {
traceId: "trc_readonly",
runnerKind: "hwlab-readonly-runner",
sessionMode: "controlled-readonly-session-registry",
turn: 1
},
blockers: [
{ code: "stdio_protocol_not_wired" }
]
}
});
assert.equal(summary.kind, "read-only-session-tools");
assert.equal(summary.label, "只读长会话工具");
assert.equal(summary.tone, "warn");
assert.equal(summary.sessionId, "ses_readonly");
assert.equal(summary.sessionIdStatus, "ses_readonly / idle / idle");
assert.equal(summary.workspace, "/workspace/hwlab");
assert.equal(summary.sandbox, "read-only");
assert.equal(summary.runnerKind, "hwlab-readonly-runner");
assert.equal(summary.toolCalls, "1/1 pwd(completed)");
assert.equal(summary.skills, "not_requested:count=0");
assert.match(summary.runnerTrace, /runnerKind=hwlab-readonly-runner/u);
assert.equal(summary.readinessBlockers.includes("stdio_protocol_not_wired"), true);
assert.equal(summary.lastTraceId, "trc_readonly");
});
test("summarizes Codex runtimeContract blockers from health availability", () => {
const summary = classifyCodeAgentStatusSummary({
availability: {
status: "partial",
ready: false,
provider: "codex-readonly-runner",
backend: "hwlab-cloud-api/codex-readonly-runner",
capabilityLevel: "read-only-session-tools",
sessionMode: "controlled-readonly-session-registry",
runner: {
kind: "hwlab-readonly-runner",
writeCapable: false
},
runtimeContract: {
binary: { status: "missing" },
lifecycleSupervisor: { status: "blocked" },
stdioProtocol: { status: "blocked" }
}
}
});
assert.equal(summary.kind, "read-only-session-tools");
assert.equal(summary.tone, "warn");
assert.equal(summary.readinessBlockers.includes("codex_cli_binary_missing"), true);
assert.equal(summary.readinessBlockers.includes("runner_lifecycle_missing"), true);
assert.equal(summary.readinessBlockers.includes("stdio_protocol_not_wired"), true);
});
test("maps text fallback to warning with safe labels", () => {
const summary = classifyCodeAgentStatusSummary({
availability: {
status: "available",
ready: true,
provider: "openai-responses",
mode: "openai",
backend: "hwlab-cloud-api/openai-responses",
capabilityLevel: "text-chat-only",
runner: {
kind: "openai-responses-fallback"
}
}
});
assert.equal(summary.kind, "fallback-text-chat-only");
assert.equal(summary.label, "会话降级");
assert.equal(summary.tone, "warn");
assert.equal(summary.provider, "openai-responses");
assert.equal(summary.capabilityLevel, "text-chat-only");
assert.equal(summary.sessionLifecycleStatus, "failed");
assert.match(summary.sessionLifecycleHint, /fallback\/text-only\/read-only/u);
});
test("maps stateless one-shot runner separately from long-lived sessions", () => {
const summary = classifyCodeAgentStatusSummary({
latestMessage: {
status: "completed",
provider: "codex-cli",
backend: "hwlab-cloud-api/codex-cli",
capabilityLevel: "text-chat-only",
sessionMode: "ephemeral-one-shot",
runner: {
kind: "codex-cli-one-shot-ephemeral"
},
runnerLimitations: ["one-shot", "not-durable-session"],
traceId: "trc_one_shot"
}
});
assert.equal(summary.kind, "stateless-one-shot");
assert.equal(summary.label, "一次性执行");
assert.equal(summary.tone, "warn");
assert.equal(summary.sessionMode, "ephemeral-one-shot");
assert.equal(summary.lastTraceId, "trc_one_shot");
});
test("summarizes active Code Agent running request as pending with trace and session context", () => {
const summary = classifyCodeAgentStatusSummary({
latestMessage: {
role: "agent",
status: "running",
sourceKind: "PENDING",
traceId: "trc_pending_heavy_skills",
conversationId: "cnv_pending_heavy_skills",
sessionId: "cnv_pending_heavy_skills"
}
});
assert.equal(summary.kind, "busy");
assert.equal(summary.label, "会话忙/请等待");
assert.equal(summary.tone, "pending");
assert.equal(summary.codeAgentStatus, "running");
assert.equal(summary.sessionId, "cnv_pending_heavy_skills");
assert.equal(summary.sessionLifecycleStatus, "busy");
assert.match(summary.sessionLifecycleHint, /会话忙\/请等待/u);
assert.equal(summary.lastTraceId, "trc_pending_heavy_skills");
assert.equal(summary.readinessBlockers.length, 0);
});
test("summarizes canceled Code Agent request with preserved retry context", () => {
const summary = classifyCodeAgentStatusSummary({
latestMessage: {
role: "agent",
status: "canceled",
traceId: "trc_cancel_keep_context",
conversationId: "cnv_cancel_keep_context",
sessionId: "ses_cancel_keep_context",
session: {
sessionId: "ses_cancel_keep_context",
status: "canceled"
},
runnerTrace: {
traceId: "trc_cancel_keep_context",
sessionStatus: "canceled",
lastEvent: {
type: "cancel",
label: "cancel:canceled",
status: "canceled"
}
},
error: {
code: "codex_stdio_canceled",
message: "请求已取消"
}
}
});
assert.equal(summary.kind, "canceled");
assert.equal(summary.label, "请求已取消");
assert.equal(summary.tone, "blocked");
assert.equal(summary.codeAgentStatus, "canceled");
assert.equal(summary.sessionId, "ses_cancel_keep_context");
assert.equal(summary.sessionStatus, "canceled");
assert.equal(summary.sessionLifecycleStatus, "interrupted");
assert.match(summary.sessionLifecycleHint, /已中断/u);
assert.equal(summary.lastTraceId, "trc_cancel_keep_context");
});
test("summarizes timed out Code Agent request with preserved trace context", () => {
const summary = classifyCodeAgentStatusSummary({
latestMessage: {
role: "agent",
status: "timeout",
traceId: "trc_timeout_keep_context",
conversationId: "cnv_timeout_keep_context",
sessionId: "ses_timeout_keep_context",
session: {
sessionId: "ses_timeout_keep_context",
status: "timeout"
},
runnerTrace: {
traceId: "trc_timeout_keep_context",
sessionStatus: "timeout",
lastEvent: {
type: "session",
label: "session:timeout",
status: "timeout"
}
},
error: {
code: "codex_stdio_timeout",
message: "请求超时"
}
}
});
assert.equal(summary.kind, "timeout");
assert.equal(summary.label, "等待超时");
assert.equal(summary.tone, "blocked");
assert.equal(summary.codeAgentStatus, "timeout");
assert.equal(summary.sessionId, "ses_timeout_keep_context");
assert.equal(summary.sessionStatus, "timeout");
assert.equal(summary.sessionLifecycleStatus, "failed");
assert.equal(summary.lastTraceId, "trc_timeout_keep_context");
});
test("surfaces expired and failed Code Agent session lifecycle hints", () => {
const expired = classifyCodeAgentStatusSummary({
latestMessage: {
status: "failed",
provider: "codex-stdio",
session: {
sessionId: "ses_expired_ui",
status: "expired",
codexStdio: true
},
error: {
code: "session_expired"
}
}
});
assert.equal(expired.kind, "session-expired");
assert.equal(expired.label, "会话已过期");
assert.equal(expired.sessionLifecycleStatus, "expired");
assert.match(expired.sessionLifecycleHint, /重新发送建立新的 Code Agent session/u);
const failed = classifyCodeAgentStatusSummary({
latestMessage: {
status: "failed",
provider: "codex-stdio",
session: {
sessionId: "ses_failed_ui",
status: "failed",
codexStdio: true
},
error: {
code: "session_failed"
}
}
});
assert.equal(failed.kind, "turn-failed-session-continuable");
assert.equal(failed.label, "当前轮次失败");
assert.equal(failed.sessionLifecycleStatus, "failed");
assert.match(failed.sessionLifecycleHint, /session\/thread 已保留/u);
});
test("missing Code Agent session evidence is shown as lifecycle degradation", () => {
const summary = classifyCodeAgentStatusSummary({
latestMessage: {
status: "completed",
provider: "codex-stdio",
capabilityLevel: "long-lived-codex-stdio-session",
sessionMode: "codex-app-server-stdio-long-lived",
implementationType: "repo-owned-codex-app-server-stdio-session",
runner: {
kind: "codex-app-server-stdio-runner",
codexStdio: true,
writeCapable: true
},
blocker: {
code: "code_agent_session_evidence_missing"
}
}
});
assert.notEqual(summary.tone, "ok");
assert.equal(summary.sessionLifecycleLabel, "会话降级");
assert.match(summary.sessionLifecycleHint, /会话证据不完整/u);
});
test("maps blockers to blocked tone and redacts secret-like fields", () => {
const summary = classifyCodeAgentStatusSummary({
availability: {
status: "blocked",
ready: false,
provider: "openai-responses",
backend: "Secret hwlab-code-agent-provider should not show",
capabilityLevel: "blocked",
reason: "OPENAI_API_KEY_missing",
error: {
code: "provider_unavailable",
providerStatus: 503
},
missingEnv: ["OPENAI_API_KEY"],
traceId: "trc_blocked"
}
});
assert.equal(summary.kind, "blocked");
assert.equal(summary.label, "服务受阻");
assert.equal(summary.tone, "blocked");
assert.equal(summary.backend, "已隐藏");
assert.equal(summary.readinessBlockers.includes("provider_config_blocked"), true);
assert.equal(summary.readinessBlockers.includes("provider_unavailable"), true);
assert.equal(summary.readinessBlockers.includes("provider_http_503"), true);
assert.equal(summary.lastTraceId, "trc_blocked");
});
test("uses structured readiness current blockers and ignores stale provider blockers", () => {
const summary = classifyCodeAgentStatusSummary({
live: {
restIndex: {
ok: true,
status: 200,
data: {
readiness: {
codeAgent: {
status: "blocked",
ready: false,
providerReady: true,
durableDbReady: true,
sessionRunnerReady: true,
codexStdioFeasible: false,
currentBlocker: "codex_stdio_supervisor_disabled",
currentBlockers: ["codex_stdio_supervisor_disabled"],
provider: {
status: "ready",
ready: true,
provider: "openai-responses",
backend: "hwlab-cloud-api/openai-responses",
mode: "openai",
blocker: null
},
dbDurable: {
status: "ready",
ready: true,
adapter: "postgres",
blocker: null,
queryResult: "durable_readiness_ready"
},
sessionRunner: {
status: "read_only_long_lived_ready",
ready: true,
kind: "hwlab-readonly-runner",
mode: "controlled-readonly-session-registry",
capabilityLevel: "read-only-session-tools",
longLivedSession: true,
durableSession: false,
codexStdio: false,
writeCapable: false,
blocker: null
},
codexStdio: {
status: "blocked",
ready: false,
feasible: false,
blocker: "codex_stdio_supervisor_disabled",
blockerCodes: ["codex_stdio_supervisor_disabled"]
}
}
},
codeAgent: {
status: "partial",
ready: false,
provider: "openai-responses",
backend: "hwlab-cloud-api/openai-responses",
capabilityLevel: "read-only-session-tools",
blockerCodes: [
"provider_unavailable",
"runtime_durable_adapter_auth_blocked"
]
}
}
}
}
});
assert.equal(summary.kind, "read-only-session-tools");
assert.equal(summary.tone, "warn");
assert.equal(summary.provider, "openai-responses");
assert.equal(summary.capabilityLevel, "read-only-session-tools");
assert.deepEqual(summary.readinessBlockers, ["codex_stdio_supervisor_disabled"]);
assert.equal(summary.readinessBlockers.includes("provider_unavailable"), false);
assert.equal(summary.readinessBlockers.includes("runtime_durable_adapter_auth_blocked"), false);
});
test("structured readiness without codeAgent payload degrades into blocked status", () => {
const summary = classifyCodeAgentStatusSummary({
live: {
healthLive: {
ok: true,
status: 200,
data: {
readiness: {
codeAgent: {
status: "blocked",
ready: false,
providerReady: false,
durableDbReady: true,
sessionRunnerReady: false,
codexStdioFeasible: false,
currentBlocker: "provider_config_blocked",
currentBlockers: ["provider_config_blocked"],
provider: {
status: "blocked",
ready: false,
provider: "openai-responses",
backend: "hwlab-cloud-api/openai-responses",
mode: "openai",
blocker: "provider_config_blocked"
},
sessionRunner: {
status: "blocked",
ready: false,
kind: "unknown",
mode: "unknown",
capabilityLevel: "blocked",
blocker: "session_runner_blocked"
},
codexStdio: {
status: "blocked",
ready: false,
blocker: "codex_stdio_supervisor_disabled",
blockerCodes: ["codex_stdio_supervisor_disabled"]
}
}
}
}
}
}
});
assert.equal(summary.kind, "blocked");
assert.equal(summary.label, "服务受阻");
assert.equal(summary.tone, "blocked");
assert.equal(summary.readinessBlockers.includes("provider_config_blocked"), true);
assert.equal(summary.provider, "openai-responses");
});