Skip to content
Draft
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
43 changes: 41 additions & 2 deletions apps/desktop/renderer-architecture.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@
"src/renderer/live-turn-reconciler.tsx",
"src/renderer/live-turn-snapshot.ts",
"src/renderer/local-memory-digest.ts",
"src/renderer/locales/agent-graph-copy.ts",
"src/renderer/locales/artifact-copy.ts",
"src/renderer/locales/browser-copy.ts",
"src/renderer/locales/conversation-copy.ts",
"src/renderer/locales/external-session-import-copy.ts",
"src/renderer/locales/mcp-copy.ts",
"src/renderer/locales/onboarding-copy.ts",
"src/renderer/locales/peer-mesh-copy.ts",
"src/renderer/locales/permission-center-copy.ts",
"src/renderer/locales/plan-mode-copy.ts",
"src/renderer/locales/session-collaboration-copy.ts",
Expand All @@ -87,6 +89,7 @@
"src/renderer/locales/settings-web-search-copy.ts",
"src/renderer/locales/shell-copy.ts",
"src/renderer/locales/shell-remaining-copy.ts",
"src/renderer/locales/task-readiness-copy.ts",
"src/renderer/main.tsx",
"src/renderer/mcp-brand-contrast.ts",
"src/renderer/mcp-brand-marks.tsx",
Expand Down Expand Up @@ -444,8 +447,8 @@
"@maka/core/text-file-import": 1,
"@maka/core/ui-locale": 1
},
"importSpecifiers": 6,
"nonTriviaTokens": 515
"importSpecifiers": 5,
"nonTriviaTokens": 504
},
"src/renderer/app-shell-detail-panel.tsx": {
"importDeclarations": 1,
Expand Down Expand Up @@ -1161,6 +1164,7 @@
"dependencyPaths": {
"./agent-graph-panel-visibility.js": 1,
"./agent-graph-refresh.js": 1,
"./locales/agent-graph-copy.js": 1,
"@astryxdesign/core/Banner": 1,
"@astryxdesign/core/Button": 1,
"@astryxdesign/core/EmptyState": 1,
Expand Down Expand Up @@ -1677,6 +1681,18 @@
"@maka/core/local-memory": 1
}
},
"src/renderer/locales/agent-graph-copy.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {
"@maka/core/ui-locale": 1,
"@maka/runtime/stream-graph-read-model": 1
}
},
"src/renderer/locales/artifact-copy.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
Expand Down Expand Up @@ -1748,6 +1764,18 @@
"@maka/core/ui-locale": 1
}
},
"src/renderer/locales/peer-mesh-copy.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {
"@maka/core/ui-locale": 1,
"@maka/runtime-host/protocol": 1
}
},
"src/renderer/locales/permission-center-copy.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
Expand Down Expand Up @@ -1980,6 +2008,17 @@
"@maka/core/ui-locale": 1
}
},
"src/renderer/locales/task-readiness-copy.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {
"@maka/core/ui-locale": 1
}
},
"src/renderer/mcp-brand-contrast.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
Expand Down
23 changes: 13 additions & 10 deletions apps/desktop/src/main/notifications-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import type { UiLocale } from '@maka/core/ui-locale';
import type { UiCatalog, UiLocale } from '@maka/core/ui-locale';

/**
* Pure decision + copy helpers for desktop run-completion notifications.
Expand Down Expand Up @@ -77,19 +77,22 @@ export interface RunNotificationCopy {
* could not supply a session name / reply preview (e.g. an untitled
* session or a tool-only turn with no assistant text).
*/
const RUN_NOTIFICATION_COPY = {
zh: {
errored: { title: '任务出错', body: '本轮回答未能完成,点击查看详情。' },
completed: { title: '回答已生成', body: 'Maka 已完成本轮回答,点击查看。' },
},
en: {
errored: { title: 'Conversation error', body: 'This response did not finish. Click to view details.' },
completed: { title: 'Response ready', body: 'Maka finished this response. Click to view it.' },
},
} satisfies UiCatalog<Record<RunNotificationKind, RunNotificationCopy>>;

export function runNotificationCopy(
kind: RunNotificationKind,
locale: UiLocale,
): RunNotificationCopy {
if (locale === 'en') {
return kind === 'errored'
? { title: 'Conversation error', body: 'This response did not finish. Click to view details.' }
: { title: 'Response ready', body: 'Maka finished this response. Click to view it.' };
}
if (kind === 'errored') {
return { title: '任务出错', body: '本轮回答未能完成,点击查看详情。' };
}
return { title: '回答已生成', body: 'Maka 已完成本轮回答,点击查看。' };
return RUN_NOTIFICATION_COPY[locale][kind];
}

/** Renderer-supplied content for a finished turn. Both fields are
Expand Down
159 changes: 4 additions & 155 deletions apps/desktop/src/renderer/agent-graph-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@

import { useEffect, useId, useMemo, useRef, useState, type JSX } from 'react';
import type { UiLocale } from '@maka/core/ui-locale';
import type {
AgentGraphClientOperator,
AgentGraphClientSnapshot,
} from '@maka/runtime/stream-graph-read-model';
import type { AgentGraphClientSnapshot } from '@maka/runtime/stream-graph-read-model';
import type { AgentGraphEpochDirectory } from '@maka/runtime-host/client';
import type { AgentGraphEpochSummary } from '@maka/runtime-host/protocol';
import { IconButton, Selector, type SelectorOptionType } from '@maka/ui';
Expand All @@ -42,6 +39,9 @@ import {
createAgentGraphRefreshScheduler,
type AgentGraphRefreshScheduler,
} from './agent-graph-refresh.js';
import { getAgentGraphPanelCopy } from './locales/agent-graph-copy.js';

export { getAgentGraphPanelCopy };

const noopAgentGraphRefreshScheduler: AgentGraphRefreshScheduler = {
requestRefresh() {},
Expand All @@ -50,129 +50,6 @@ const noopAgentGraphRefreshScheduler: AgentGraphRefreshScheduler = {
dispose() {},
};

type GraphPanelCopy = {
title: string;
loading: string;
retry: string;
collapse: string;
expand: string;
dismiss: string;
stop: string;
stopping: string;
stopFailed: string;
loadFailed: string;
openSession: string;
operators: string;
selectedResults: string;
epoch: string;
currentEpoch: string;
historicalEpoch: string;
cappedEpochs(count: number): string;
noOperators: string;
hiddenOperators(count: number): string;
progress(settled: number, total: number, hasOmitted: boolean): string;
status(status: AgentGraphClientSnapshot['status']): string;
operatorStatus(status: AgentGraphClientOperator['status']): string;
wait(operator: AgentGraphClientOperator): string | undefined;
};

export function getAgentGraphPanelCopy(locale: UiLocale): GraphPanelCopy {
if (locale === 'zh') {
return {
title: 'Agent Graph',
loading: '正在读取 Graph 状态…',
retry: '重试',
collapse: '收起 Agent Graph',
expand: '展开 Agent Graph',
dismiss: '关闭 Agent Graph',
stop: '停止 Graph',
stopping: '停止中…',
stopFailed: '停止 Graph 失败,请重试。',
loadFailed: 'Graph 状态刷新失败。',
openSession: '打开子任务',
operators: 'Operators',
selectedResults: '已选择结果',
epoch: 'Graph 运行轮次',
currentEpoch: '当前',
historicalEpoch: '历史记录(只读)',
cappedEpochs: (count) => `仅显示最近 ${count} 次运行`,
noOperators: '等待主 Agent 创建 operator…',
hiddenOperators: (count) => `另有 ${count} 个 operator`,
progress: (settled, total, hasOmitted) =>
hasOmitted ? `可见 ${settled}/${total} 已结束` : `${settled}/${total} 已结束`,
status: (status) =>
({
empty: '等待调度',
active: '运行中',
closing: '收尾中',
waiting: '等待中',
stopped: '已停止',
failed: '失败',
completed: '已完成',
})[status],
operatorStatus: (status) =>
({
not_started: '未启动',
waiting: '等待',
runnable: '可运行',
running: '运行中',
blocked: '受阻',
completed: '完成',
failed: '失败',
aborted: '中止',
cancelled: '取消',
})[status],
wait: waitReasonZh,
};
}
return {
title: 'Agent Graph',
loading: 'Loading graph state…',
retry: 'Retry',
collapse: 'Collapse Agent Graph',
expand: 'Expand Agent Graph',
dismiss: 'Dismiss Agent Graph',
stop: 'Stop graph',
stopping: 'Stopping…',
stopFailed: 'Could not stop the graph. Try again.',
loadFailed: 'Could not refresh graph state.',
openSession: 'Open child task',
operators: 'Operators',
selectedResults: 'Selected results',
epoch: 'Graph run',
currentEpoch: 'Current',
historicalEpoch: 'History (read-only)',
cappedEpochs: (count) => `Showing the newest ${count} runs`,
noOperators: 'Waiting for the main agent to create an operator…',
hiddenOperators: (count) => `${count} more operator${count === 1 ? '' : 's'}`,
progress: (settled, total, hasOmitted) =>
hasOmitted ? `${settled}/${total} visible settled` : `${settled}/${total} settled`,
status: (status) =>
({
empty: 'Awaiting schedule',
active: 'Running',
closing: 'Finishing',
waiting: 'Waiting',
stopped: 'Stopped',
failed: 'Failed',
completed: 'Completed',
})[status],
operatorStatus: (status) =>
({
not_started: 'Not started',
waiting: 'Waiting',
runnable: 'Runnable',
running: 'Running',
blocked: 'Blocked',
completed: 'Completed',
failed: 'Failed',
aborted: 'Aborted',
cancelled: 'Cancelled',
})[status],
wait: waitReasonEn,
};
}

export function AgentGraphPanel(props: {
rootSessionId: string;
enabled: boolean;
Expand Down Expand Up @@ -538,31 +415,3 @@ function sameEpochPage(
);
});
}

function firstWait(operator: AgentGraphClientOperator) {
return operator.readiness.find((readiness) => readiness.status === 'waiting')?.waitingFor[0];
}

function waitReasonEn(operator: AgentGraphClientOperator): string | undefined {
const wait = firstWait(operator);
if (!wait) return undefined;
if (wait.kind === 'input_route') {
return `Waiting for input from ${wait.upstreamOperatorIds.join(', ')}`;
}
if (wait.kind === 'activation_missing') {
return `Waiting for ${wait.operatorId} activation`;
}
return `Waiting for ${wait.operatorId} to settle`;
}

function waitReasonZh(operator: AgentGraphClientOperator): string | undefined {
const wait = firstWait(operator);
if (!wait) return undefined;
if (wait.kind === 'input_route') {
return `等待 ${wait.upstreamOperatorIds.join('、')} 的输入`;
}
if (wait.kind === 'activation_missing') {
return `等待 ${wait.operatorId} activation`;
}
return `等待 ${wait.operatorId} 结束`;
}
4 changes: 2 additions & 2 deletions apps/desktop/src/renderer/app-shell-copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import type { ConnectionTestResult } from '@maka/core/llm-connections';
import type { TextFileImportPreflightFailureReason } from '@maka/core/text-file-import';
import type { UiLocale } from '@maka/core/ui-locale';
import { generalizedErrorMessage, generalizedErrorMessageChinese } from '@maka/core/redaction';
import { generalizedErrorMessageForLocale } from '@maka/core/redaction';
import { getShellCopy } from './locales/shell-copy.js';

const SESSION_READ_MESSAGES_ERROR_MARKER = 'MAKA_SESSION_READ_MESSAGES_ERROR:';
Expand All @@ -42,7 +42,7 @@ function sessionMessageErrorMessage(error: unknown, fallback: string, locale: Ui
}

function localizedErrorMessage(error: unknown, fallback: string, locale: UiLocale): string {
return locale === 'zh' ? generalizedErrorMessageChinese(error, fallback) : generalizedErrorMessage(error, fallback);
return generalizedErrorMessageForLocale(locale, error, fallback);
}

export function commandPaletteActionErrorMessage(error: unknown, fallback: string, locale: UiLocale): string {
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/renderer/daily-review-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type { DailyReviewArchive } from '@maka/core/daily-review';
import type { UiLocale } from '@maka/core/ui-locale';
import { dailyReviewArchiveId } from '@maka/core/daily-review';

import { generalizedErrorMessage, generalizedErrorMessageChinese } from '@maka/core/redaction';
import { generalizedErrorMessageForLocale } from '@maka/core/redaction';

export function dailyReviewExportDefaultName(
input: Pick<DailyReviewArchive, 'day' | 'range'>,
Expand All @@ -30,5 +30,5 @@ export function dailyReviewExportDefaultName(
}

export function dailyReviewActionErrorMessage(error: unknown, fallback: string, locale: UiLocale): string {
return locale === 'zh' ? generalizedErrorMessageChinese(error, fallback) : generalizedErrorMessage(error, fallback);
return generalizedErrorMessageForLocale(locale, error, fallback);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { generalizedErrorMessage, generalizedErrorMessageChinese, redactSecrets } from '@maka/core/redaction';
import { generalizedErrorMessageForLocale, redactSecrets } from '@maka/core/redaction';
import { type ConnectionTestResult } from '@maka/core/llm-connections';
import { type UiLocale } from '@maka/core/ui-locale';
import { getProviderSettingsCopy } from './settings-provider-copy.js';
Expand All @@ -42,9 +42,7 @@ export function providerPanelActionErrorMessage(error: unknown, locale: UiLocale
? '连接状态已更新,请刷新列表后再删除。'
: 'The connection changed while deleting. Refresh the list and try again.';
}
const classified = locale === 'zh'
? generalizedErrorMessageChinese(new Error(cleaned), '')
: generalizedErrorMessage(new Error(cleaned), '');
const classified = generalizedErrorMessageForLocale(locale, new Error(cleaned), '');
return classified || shared.actionFallback;
}

Expand Down Expand Up @@ -83,9 +81,7 @@ export function connectionTestFailureMessage(
): string {
const fallback = connectionTestFailureFallback(result, copy, locale);
if (!result.errorMessage) return fallback;
return locale === 'zh'
? generalizedErrorMessageChinese(new Error(result.errorMessage), fallback)
: generalizedErrorMessage(new Error(result.errorMessage), fallback);
return generalizedErrorMessageForLocale(locale, new Error(result.errorMessage), fallback);
}

export function connectionLastTestMessageDisplay(message: string | undefined, locale: UiLocale = 'zh'): string | undefined {
Expand All @@ -96,8 +92,6 @@ export function connectionLastTestMessageDisplay(message: string | undefined, lo
const copy = getProviderSettingsCopy(locale).shared;
const known = (copy.lastTest as Readonly<Record<string, string>>)[normalized];
if (known) return known;
const classified = locale === 'zh'
? generalizedErrorMessageChinese(new Error(trimmed), '')
: generalizedErrorMessage(new Error(trimmed), '');
const classified = generalizedErrorMessageForLocale(locale, new Error(trimmed), '');
return classified || copy.statusUnavailable;
}
Loading