Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions apps/web/src/features/metrics/CoreMetricsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { AgentCoreError, type CoreJobStatus, type CoreMetrics, type CoreMetricsRange } from "@oac/agents-client";
import { type CoreJobStatus, type CoreMetrics, type CoreMetricsRange } from "@oac/agents-client";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { Network } from "lucide-react";
import { useMemo, useState, type ReactNode } from "react";
import { useTranslation } from "react-i18next";

Expand Down Expand Up @@ -55,17 +54,14 @@ export function CoreMetricsPage() {
const [range, setRange] = useState<CoreMetricsRange>("1h");
const query = useQuery({ ...coreMetricsQuery(range), placeholderData: keepPreviousData, refetchInterval: REFRESH_MS, refetchIntervalInBackground: false });
const metrics = query.data ?? null;
const missing = query.error instanceof AgentCoreError && (query.error.status === 404 || query.error.status === 501);
const error = query.isError ? coreError(query.error, tCommon) : "";
useFailureToast(metrics !== null && query.isError, t("core.stale", { reason: error }), "core-metrics-refresh");

let body: ReactNode;
if (!metrics) {
body = missing
? <EmptyState icon={Network} title={t("core.missingTitle")} hint={t("core.missingDescription")} />
: query.isError
? <p className="page-status" role="alert">{t("core.failed", { reason: error })}</p>
: <DashboardSkeleton label={t("core.loading")} figures={5} />;
body = query.isError
? <p className="page-status" role="alert">{t("core.failed", { reason: error })}</p>
: <DashboardSkeleton label={t("core.loading")} figures={5} />;
} else {
body = <CoreMetricsBody metrics={metrics} />;
}
Expand Down
15 changes: 0 additions & 15 deletions apps/web/src/features/skills/skill-operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,12 @@ import { AgentCoreError, type Skill, type SkillVersion } from "@oac/agents-clien
import type { ProjectClient } from "../../lib/projects";
import { appendCollectionPage } from "../../lib/collection-pagination";

/**
* Skill navigation support, from the first Skill list request:
* - `supported`: the list succeeded;
* - `unsupported`: 404 or 405, an older Core without Skills (hide the entry);
* - `error`: anything else (show the entry with a retry).
*/
export type SkillsSupport = "supported" | "unsupported" | "error";

export const SKILLS_PAGE_SIZE = 20;

export function isAbortError(error: unknown): boolean {
return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
}

export function classifySkillsError(error: unknown): Exclude<SkillsSupport, "supported"> {
if (error instanceof AgentCoreError) {
if (error.status === 404 || error.status === 405) return "unsupported";
}
return "error";
}

/** Core rejects deleting the default while other versions remain (400 invalid_value on `version`). */
export function isDefaultVersionConflict(error: unknown): boolean {
return error instanceof AgentCoreError && error.status === 400 && error.code === "invalid_value" && error.param === "version";
Expand Down
2 changes: 0 additions & 2 deletions apps/web/src/i18n/locales/en/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ export const metrics = {
loading: "Reading Core metrics…",
failed: "Core metrics could not be read. {{reason}}",
stale: "Refresh failed; showing the last metrics read. {{reason}}",
missingTitle: "Core does not report its own metrics yet",
missingDescription: "Core needs to provide /core/v1/metrics before execution, database and background jobs can show.",
kpiLabel: "Core summary",
meta: "{{status}} · {{revision}} · up {{uptime}}",
notOwner: "Does not hold the execution lease",
Expand Down
28 changes: 1 addition & 27 deletions apps/web/src/i18n/locales/en/sessions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { coreHarnessNames } from "@oac/agents-client";

/**
* Session log and one Session's read-only history (Monitor › Session log).
* `validation` and `actions.errors` serve the retired Session-creation and
* metadata helpers that the orphaned API workbench still imports; remove them
* together with that code.
*/
/** Session log and one Session's read-only history (Monitor › Session log). */
export const sessions = {
common: {
agent: "Agent", session: "Session", status: "Status", unknown: "Unknown", unavailable: "Unavailable", untitledAgent: "Unnamed Agent",
Expand Down Expand Up @@ -272,25 +267,4 @@ export const sessions = {
toolDurationSentence: "Tool-reported duration: {{duration}}.", toolDuration: "Tool-reported duration: {{duration}}", durationUnknown: "Reported duration is unknown.", durationInvalid: "The reported duration could not be interpreted.", perItemNotProvided: "Per-item timing not provided by Core.", perItemTimingMissing: "Core does not provide per-item timing.",
turnDuration: "Turn {{duration}}", turnTimeUnknown: "Turn time unknown", turnTimeNotProvided: "Turn time not provided", payloadAvailable: "Payload available", resultAvailable: "Result available", noPreview: "No preview available", configuredInstructions: "Configured instructions", userMessage: "User message", assistantMessage: "Assistant message", unsupportedItem: "Unsupported Item", agentConfiguration: "Agent configuration", turnNumber: "Turn {{number}}", unassociatedItemsNumber: "Unassociated Items {{number}}", unknownCount: "{{count}} unknown",
},
actions: {
errors: {
metadataConflict: "Metadata changed in OpenAgentCore while you were editing: {{keys}}. Your draft was kept; review the latest values before saving again.",
metadataValidJson: "Metadata must be valid JSON.", metadataObject: "Metadata must be a JSON object.", metadataStringValues: "Every metadata value must be a string.",
metadataTitleField: "Edit title in the Title field, not in additional metadata.", metadataMaxPairs: "Session metadata supports at most 16 pairs, including title.", metadataLength: "Metadata keys must be at most 64 characters and values at most 512 characters.",
invalidRetrieval: "OpenAgentCore returned an invalid Session retrieval response. The Web kept its current durable view and did not send a write.",
updateLabel: "update", deletionLabel: "deletion", notFound: "This Session was not found in OpenAgentCore. The Web kept its current durable view; refresh Sessions before trying again.",
busyDelete: "OpenAgentCore deletes a Session only when it is idle or failed without required actions. This Session still has queued, running or waiting work or pending input, so nothing was changed. Choose Cancel work and delete to cancel it, wait until it is idle and then delete it.",
readLifecycleConflict: "The latest Session could not be retrieved because this compatible Core returned a lifecycle conflict (409), so no update request was sent. Your draft and current durable view were kept.",
writeLifecycleConflict: "This compatible Core rejected the Session {{action}} because it conflicts with the current lifecycle state. The Web did not retry.",
noUpdateSent: "No update request was sent.", unknownWriteSuffix: "The write result is unknown. The Web kept its current durable view and did not retry; refresh before deciding whether to try again.",
coreUnavailable: "OpenAgentCore could not complete the Session {{action}} ({{status}}). {{suffix}}", uncertainStatus: "The Session {{action}} result is uncertain after OpenAgentCore returned {{status}}. The Web kept its current durable view and did not retry; refresh before deciding whether to try again.",
readFailureWithDetail: "{{detail}} No update request was sent; your draft and current durable view were kept.", writeFailureWithDetail: "{{detail}} The Web kept its current durable view and did not retry.",
latestReadFailure: "The latest Session could not be retrieved, so no update request was sent. Your draft and the current durable view were kept.", unknownConnection: "The Session {{action}} result is unknown because the connection ended before Core confirmed it. The Web kept its current durable view and did not retry; refresh before deciding whether to try again.",
invalidUpdateConfirmation: "OpenAgentCore returned an invalid Session update confirmation. The write result is unknown; the Web kept its current durable view and did not retry.",
inputPending: "OpenAgentCore deletes a Session only when it is idle or failed without required actions. This Session has input waiting to start in its Environment, which cannot be cancelled, so nothing was changed. Delete it after that input starts, expires or fails; once it starts, cancel its work first.",
invalidDeletionConfirmation: "OpenAgentCore returned an invalid deletion confirmation. The Web kept the Session; refresh durable state before taking another action.",
cancelRejected: "OpenAgentCore rejected the cancellation ({{status}}): {{detail}}", cancelUnknown: "The cancellation result is unknown because the connection ended before Core confirmed it.", cancelDeleteKept: "{{detail}} The Session was not deleted and the Web did not retry.",
waitReadFailure: "Cancellation was requested, but the Session could not be read while waiting for it to become idle. It was not deleted.", waitTimeout: "Cancellation was requested, but the Session was still {{status}} after {{seconds}} seconds. It was not deleted; try again once it is idle.",
},
},
} as const;
2 changes: 0 additions & 2 deletions apps/web/src/i18n/locales/zh-CN/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ export const metrics = {
loading: "正在读取 Core 指标…",
failed: "无法读取 Core 指标。{{reason}}",
stale: "刷新失败,显示的是上次读取的指标。{{reason}}",
missingTitle: "Core 尚未上报自身指标",
missingDescription: "需要 Core 提供 /core/v1/metrics,才能显示执行、数据库和后台任务。",
kpiLabel: "Core 概况",
meta: "{{status}} · {{revision}} · 已运行 {{uptime}}",
notOwner: "未持有执行归属",
Expand Down
23 changes: 0 additions & 23 deletions apps/web/src/i18n/locales/zh-CN/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,27 +272,4 @@ export const sessions = {
toolDurationSentence: "工具报告耗时:{{duration}}。", toolDuration: "工具报告耗时:{{duration}}", durationUnknown: "报告的耗时未知。", durationInvalid: "无法解析报告的耗时。", perItemNotProvided: "Core 未提供逐 Item 时间。", perItemTimingMissing: "Core 不提供逐 Item 时间。",
turnDuration: "Turn {{duration}}", turnTimeUnknown: "Turn 耗时未知", turnTimeNotProvided: "未提供 Turn 耗时", payloadAvailable: "载荷可用", resultAvailable: "结果可用", noPreview: "无可用预览", configuredInstructions: "已配置指令", userMessage: "用户消息", assistantMessage: "助手消息", unsupportedItem: "不支持的 Item", agentConfiguration: "Agent 配置", turnNumber: "Turn {{number}}", unassociatedItemsNumber: "未关联 Item {{number}}", unknownCount: "{{count}} 个未知",
},
actions: {
...english.actions,
errors: {
...english.actions.errors,
metadataConflict: "你编辑期间 OpenAgentCore 中的元数据已发生变化:{{keys}}。草稿已保留;请检查最新值后再保存。",
metadataValidJson: "元数据必须是有效的 JSON。", metadataObject: "元数据必须是 JSON 对象。", metadataStringValues: "每个元数据值都必须是字符串。",
metadataTitleField: "请在“标题”字段中编辑标题,不要放在其他元数据中。", metadataMaxPairs: "Session 元数据最多支持 16 个键值对(包括标题)。", metadataLength: "元数据键最多 64 个字符,值最多 512 个字符。",
invalidRetrieval: "OpenAgentCore 返回了无效的 Session 读取响应。Web 已保留当前持久化视图,且未发送写入请求。",
updateLabel: "更新", deletionLabel: "删除", notFound: "OpenAgentCore 中未找到此 Session。Web 已保留当前持久化视图;请刷新 Session 后重试。",
busyDelete: "OpenAgentCore 仅允许删除处于空闲或失败状态且没有必需操作的 Session。此 Session 仍有排队、运行、等待中的工作或待处理输入,因此未做任何更改。请选择“取消工作并删除”,等待 Session 空闲后再删除。",
readLifecycleConflict: "读取最新 Session 时,兼容的 Core 返回了生命周期冲突(409),因此未发送更新请求。草稿和当前持久化视图均已保留。",
writeLifecycleConflict: "兼容的 Core 拒绝了 Session{{action}},因为它与当前生命周期状态冲突。Web 未自动重试。",
noUpdateSent: "未发送更新请求。", unknownWriteSuffix: "写入结果未知。Web 已保留当前持久化视图且未自动重试;请刷新状态后再决定是否重试。",
coreUnavailable: "OpenAgentCore 无法完成 Session{{action}}({{status}})。{{suffix}}", uncertainStatus: "OpenAgentCore 返回 {{status}} 后,Session{{action}}结果不确定。Web 已保留当前持久化视图且未自动重试;请刷新状态后再决定是否重试。",
readFailureWithDetail: "{{detail}} 未发送更新请求;草稿和当前持久化视图均已保留。", writeFailureWithDetail: "{{detail}} Web 已保留当前持久化视图且未自动重试。",
latestReadFailure: "无法读取最新 Session,因此未发送更新请求。草稿和当前持久化视图均已保留。", unknownConnection: "连接在 Core 确认前中断,因此 Session{{action}}结果未知。Web 已保留当前持久化视图且未自动重试;请刷新状态后再决定是否重试。",
invalidUpdateConfirmation: "OpenAgentCore 返回了无效的 Session 更新确认。写入结果未知;Web 已保留当前持久化视图且未自动重试。",
inputPending: "OpenAgentCore 仅允许删除处于空闲或失败状态且没有必需操作的 Session。此 Session 有等待在 Environment 中启动的输入,无法取消,因此未做任何更改。请等待输入启动、过期或失败后删除;输入启动后,请先取消其工作。",
invalidDeletionConfirmation: "OpenAgentCore 返回了无效的删除确认。Web 已保留该 Session;请刷新持久化状态后再操作。",
cancelRejected: "OpenAgentCore 拒绝取消请求({{status}}):{{detail}}", cancelUnknown: "连接在 Core 确认前中断,因此取消结果未知。", cancelDeleteKept: "{{detail}} Session 未删除,Web 也未自动重试。",
waitReadFailure: "已请求取消,但等待 Session 进入空闲状态期间无法读取该 Session,因此未删除。", waitTimeout: "已请求取消,但 {{seconds}} 秒后 Session 仍处于{{status}}状态,因此未删除;请在 Session 空闲后重试。",
},
},
} as const;
59 changes: 1 addition & 58 deletions apps/web/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ html[data-theme="dark"] .brand-mark {
color: var(--fg-muted);
}

/* Shared ledger primitives and legacy Agent detail styles. */
/* Shared ledger primitives. */

.ledger {
min-height: 0;
Expand Down Expand Up @@ -712,13 +712,6 @@ html[data-theme="dark"] .brand-mark {

/* Sessions — conversation list and 48rem thread. */

.status-label {
color: var(--fg-muted);
font-size: 12px;
line-height: 16px;
text-transform: capitalize;
}

.trace-workbench {
display: flex;
min-width: 0;
Expand Down Expand Up @@ -1288,50 +1281,6 @@ html[data-theme="dark"] .brand-mark {
padding-left: 0;
}

.thread-content {
display: flex;
width: 100%;
max-width: 768px;
min-height: 100%;
flex-direction: column;
margin: 0 auto;
padding: 24px 16px;
}

.message-stack {
display: flex;
flex-direction: column;
gap: 20px;
}

.message-row {
display: flex;
width: 100%;
}

.message-row.user {
justify-content: flex-end;
}

.message-body {
display: flex;
min-width: 0;
max-width: 85%;
flex-direction: column;
color: var(--fg);
}

.message-row.user .message-body {
align-items: flex-end;
}

.message-byline {
margin-bottom: 4px;
color: var(--fg-muted);
font-size: 12px;
line-height: 16px;
}

.message-copy {
color: var(--fg);
font-size: 14px;
Expand Down Expand Up @@ -1645,12 +1594,6 @@ html[data-theme="dark"] .brand-mark {
font-size: 13.5px;
}

.message-row.user .message-copy {
padding: 8px 12px;
background: var(--surface-muted);
border-radius: 6px;
}

.work-trace {
width: 100%;
min-width: 0;
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/styles/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* The console's single stylesheet entry, in cascade order:
* 1. Tailwind's theme variables (no preflight: the console keeps its base rules);
* 2. IBM Plex Sans and Beautiful UI's foundation — the design tokens every surface uses;
* 3. the console's legacy base and grammar, whose variables alias those tokens;
* 3. the console's base and grammar, whose variables alias those tokens;
* 4. system.css, the component system in Beautiful UI's vocabulary;
* 5. Tailwind utilities last, generated only for the registry components.
*/
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/styles/system.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* (src/app/beautifui/foundation.css): cool canvas, white cards drawn by a
* hairline ring and a smooth shadow, an ink ramp for text, pill buttons with an
* ink primary, filled fields with a hairline ring, dark tooltips, and
* indigo as the only accent. Loaded after the legacy stylesheets, so every
* indigo as the only accent. Loaded after the base stylesheets, so every
* shared atom is defined here once; feature stylesheets only arrange them.
*/

Expand Down
Loading
Loading