docs: 将仓库代码注释统一为中文
CI / docs-check (push) Canceled after 0s
CI / backend-test (push) Canceled after 0s
CI / service-test (push) Canceled after 0s
CI / frontend-test (push) Canceled after 0s
CI / rust-core (push) Canceled after 0s
CI / docs-check (pull_request) Canceled after 0s
CI / backend-test (pull_request) Canceled after 0s
CI / service-test (pull_request) Canceled after 0s
CI / frontend-test (pull_request) Canceled after 0s
CI / rust-core (pull_request) Canceled after 0s
CI / docs-check (push) Canceled after 0s
CI / backend-test (push) Canceled after 0s
CI / service-test (push) Canceled after 0s
CI / frontend-test (push) Canceled after 0s
CI / rust-core (push) Canceled after 0s
CI / docs-check (pull_request) Canceled after 0s
CI / backend-test (pull_request) Canceled after 0s
CI / service-test (pull_request) Canceled after 0s
CI / frontend-test (pull_request) Canceled after 0s
CI / rust-core (pull_request) Canceled after 0s
This commit is contained in:
@@ -135,7 +135,7 @@ async function request<T>(path: string, options: RequestOptions = {}): Promise<T
|
||||
try {
|
||||
errBody = (await resp.json()) as ErrorResponse
|
||||
} catch {
|
||||
/* ignore */
|
||||
/* 忽略 */
|
||||
}
|
||||
|
||||
const code = errBody?.error?.code || `HTTP_${resp.status}`
|
||||
|
||||
@@ -37,8 +37,7 @@ export const mediaService = {
|
||||
},
|
||||
}
|
||||
|
||||
// Keep one identity until the input/options change, including a lost HTTP response.
|
||||
// Payloads remain in memory; durable uploads/jobs are owned by the backend.
|
||||
// 保留一个身份,直到输入/选项发生变化,包括丢失 HTTP 响应。有效负载保留在内存中;持久上传/作业归后端所有。
|
||||
export function createMediaSubmission() {
|
||||
let pending: {file: File; options: string; uploadKey: string; jobKey: string; attachmentId?: string} | null = null
|
||||
return {
|
||||
|
||||
@@ -5,7 +5,7 @@ export function getModelRouting(): Promise<ModelRoutingResponse> {
|
||||
return apiClient.get('/api/model-routing')
|
||||
}
|
||||
|
||||
// version is the last version read from the server (optimistic concurrency).
|
||||
// 版本是从服务器读取的最后一个版本(乐观并发)。
|
||||
export function saveModelRouting(config: ModelRoutingConfig): Promise<ModelRoutingResponse> {
|
||||
return apiClient.put('/api/model-routing', config)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { hostInvoke } from './desktop'
|
||||
|
||||
export interface RequestProgress { issued: boolean; requestId?: string }
|
||||
|
||||
/** A reservation makes cancel-before-dispatch definitive even across IPC ordering. */
|
||||
/** 即使在 IPC 订购中,预订也可以确保发货前取消。 */
|
||||
export function coreRequest<T>(args: Record<string, unknown>, signal: AbortSignal, timeoutMs: number, progress: RequestProgress): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let settled = false
|
||||
@@ -31,7 +31,7 @@ export function coreRequest<T>(args: Record<string, unknown>, signal: AbortSigna
|
||||
if (!settled) { settled = true; reject(error) }
|
||||
} finally {
|
||||
signal.removeEventListener('abort', abort)
|
||||
// Also discard a reservation if dispatch failed before Rust claimed it.
|
||||
// 如果在 Rust 声明保留之前调度失败,则也丢弃保留。
|
||||
cancel()
|
||||
}
|
||||
})()
|
||||
|
||||
@@ -4,7 +4,7 @@ import { hostInvoke } from './desktop'
|
||||
type Message = { kind: 'headers'; status: number } | { kind: 'chunk'; data: string }
|
||||
| { kind: 'done' } | { kind: 'error'; code: string }
|
||||
|
||||
/** Native session credentials stay in Rust; this channel carries response bytes only. */
|
||||
/** 本机会话凭证保留在 Rust 中;该通道仅承载响应字节。 */
|
||||
export function coreStream(path: string, init: RequestInit): Promise<Response> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const requestId = crypto.randomUUID()
|
||||
@@ -33,7 +33,7 @@ export function coreStream(path: string, init: RequestInit): Promise<Response> {
|
||||
if (message.kind === 'chunk') {
|
||||
const bytes = Uint8Array.from(atob(message.data), c => c.charCodeAt(0))
|
||||
controller.enqueue(bytes)
|
||||
// Bound queued data if a consumer stops reading without cancelling.
|
||||
// 如果消费者停止读取而不取消,则绑定排队数据。
|
||||
if ((controller.desiredSize ?? 0) < -4096) fail(new Error('CORE_STREAM_BACKPRESSURE'))
|
||||
}
|
||||
if (message.kind === 'error') fail(new Error(message.code))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Portable preference records are bound to the active Vault; local drafts retain their own Vault key. */
|
||||
/** 可移植偏好记录与主用Vault绑定;本地草稿保留自己的 Vault 密钥。 */
|
||||
import { ref, watch, nextTick } from 'vue'
|
||||
import { useWorkspaceStore } from '@/stores/workspace'
|
||||
import { useThemeStore } from '@/stores/theme'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** A durable preference draft keeps its original CAS base until the user resolves a conflict. */
|
||||
/** 持久偏好草案保留其原始 CAS 基础,直到用户解决冲突。 */
|
||||
export interface LogicalRecord<T> { schema: 1; kind: string; id: string; data: T }
|
||||
export interface RecordDocument<T> { record: LogicalRecord<T>; hash: string; file_id: string }
|
||||
interface Draft<T> { record: LogicalRecord<T>; expected: string; operation_id: string }
|
||||
@@ -40,7 +40,7 @@ export class RecordBinding<T> {
|
||||
if (this.stopped) return
|
||||
const data = JSON.parse(JSON.stringify(this.options.read())) as T
|
||||
if (!this.draft && this.remote && JSON.stringify(data) === JSON.stringify(this.remote.record.data)) return
|
||||
// New edits while a request runs get a new operation, but preserve the unresolved base.
|
||||
// 请求运行时的新编辑会获取新操作,但保留未解析的基础。
|
||||
this.draft = { record: { schema: 1, kind: this.options.kind, id: this.options.id, data }, expected: this.draft?.expected ?? this.remote?.hash ?? '', operation_id: crypto.randomUUID() }
|
||||
this.restored = false; this.invalidDraft = false
|
||||
try { this.persist(); if (this.error === 'PREFERENCE_DRAFT_STORE_FAILED') this.error = '' } catch { this.error = 'PREFERENCE_DRAFT_STORE_FAILED'; this.options.changed?.() }
|
||||
@@ -71,7 +71,7 @@ export class RecordBinding<T> {
|
||||
if (this.draft.operation_id === draft.operation_id) {
|
||||
this.persist(null); this.draft = null; this.appliedHash = committed.hash
|
||||
} else {
|
||||
// The next local edit follows the just-confirmed predecessor, not its older CAS base.
|
||||
// 下一个本地编辑遵循刚刚确认的前身,而不是其较旧的 CAS 基础。
|
||||
this.draft.expected = committed.hash; this.persist()
|
||||
}
|
||||
} else if (this.remote && this.remote.hash !== this.appliedHash) {
|
||||
|
||||
@@ -67,7 +67,7 @@ export function coerceArgument(field: CommandField, raw: string): unknown {
|
||||
return Number.isNaN(parsed) ? undefined : parsed
|
||||
}
|
||||
if (field.type === 'object' || field.type === 'array') {
|
||||
try { return JSON.parse(raw) } catch { return raw } // Backend reports the schema error without discarding the input.
|
||||
try { return JSON.parse(raw) } catch { return raw } // 后端报告模式错误而不丢弃输入。
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@ import { isMap, parseDocument } from 'yaml'
|
||||
|
||||
export const THEME_APP_VERSION = appPackage.version
|
||||
|
||||
/**
|
||||
* Semantic colors every page and component may consume. Theme packages can
|
||||
* override any subset; the compatibility layer supplies the rest.
|
||||
*/
|
||||
/** 每个页面和组件可能消耗的语义颜色。主题包可以覆盖任何子集;兼容层提供其余部分。 */
|
||||
export const REQUIRED_THEME_COLOR_TOKENS = [
|
||||
'background-primary', 'background-secondary', 'background-tertiary', 'background-hover', 'background-active', 'background-overlay',
|
||||
'surface-primary', 'surface-secondary', 'surface-elevated',
|
||||
@@ -29,7 +26,7 @@ const STORAGE_KEY = 'installed-themes'
|
||||
const ACTIVE_CUSTOM_KEY = 'active-custom-theme'
|
||||
export const MAX_THEME_BYTES = 5 * 1024 * 1024
|
||||
|
||||
/** Normalize all transports to the existing single-file inspection format. */
|
||||
/** 将所有传输标准化为现有的单文件检查格式。 */
|
||||
export async function decodeThemePackage(bytes: Uint8Array): Promise<string> {
|
||||
if (bytes.length > MAX_THEME_BYTES) throw new Error('主题包不能超过 5 MB')
|
||||
const decode = (data: Uint8Array) => new TextDecoder('utf-8', { fatal: true }).decode(data)
|
||||
@@ -180,7 +177,7 @@ function applyThemeCss(themeId: string, css: string) {
|
||||
|
||||
const THEME_CONTRACT_MARKER = '/* opennexus-theme-contract */'
|
||||
|
||||
/** Fill incomplete third-party themes with an accessible semantic palette. */
|
||||
/** 使用可访问的语义调色板填充不完整的第三方主题。 */
|
||||
export function withThemeContract(themeId: string, isDark: boolean, css: string): string {
|
||||
if (css.includes(THEME_CONTRACT_MARKER)) return css
|
||||
const selector = `[data-theme="${themeId}"]`
|
||||
@@ -408,7 +405,7 @@ export function setActiveCustomTheme(themeId: string | null) {
|
||||
const theme = themeId ? loadStoredThemes().find(item => item.theme_id === themeId) : undefined
|
||||
const storedCss = themeId ? localStorage.getItem(`${STORAGE_KEY}-css-${themeId}`) : null
|
||||
const css = themeId && theme && storedCss ? withThemeContract(themeId, theme.is_dark, storedCss) : storedCss
|
||||
// Validate before changing the current page. Only the selected theme owns a style node.
|
||||
// 更改当前页面之前进行验证。只有选定的主题才拥有样式节点。
|
||||
if (css) validateCssSafety(css)
|
||||
document.head.querySelectorAll('style[id^="theme-style-"]').forEach(style => style.remove())
|
||||
if (themeId && css) applyThemeCss(themeId, css)
|
||||
|
||||
@@ -147,7 +147,7 @@ export async function readFileContent(filePath: string): Promise<string> {
|
||||
return note.markdown
|
||||
}
|
||||
|
||||
/** Resolve the backend note identity already associated with a workspace path. */
|
||||
/** 解析已与工作空间路径关联的后端笔记标识。 */
|
||||
export async function getNoteId(filePath: string): Promise<string> {
|
||||
return requireNoteId(filePath)
|
||||
}
|
||||
@@ -163,7 +163,7 @@ export async function saveFileContent(filePath: string, content: string, expecte
|
||||
await noteService.updateNote(await requireNoteId(filePath), {
|
||||
markdown: content,
|
||||
...(expectedHash ? { expected_content_hash: expectedHash } : {}),
|
||||
// Explicit [] clears the index; absent tags retain API-managed tags.
|
||||
// 显式[]清除索引;缺失的标签保留 API 管理的标签。
|
||||
...(metadata?.hasTags ? { tags: metadata.tags } : {}),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user