Compare commits

...
Author SHA1 Message Date
weichen fac99939fa Move AdminZoneSection out of the generated contracts mirror
Why: src/contracts.ts is fully regenerated from Core by make contracts;
the hand-added interface there is deleted on every sync (surfaced as a
dirty tree in the Dev composite test run).
Evidence: npx vitest run 101/101, tsc --noEmit clean, knip 42 <= 43;
Dev composite CI is authoritative.
Impact: AdminZoneSection now lives in api.ts (backend-only endpoint
type, matching existing local-type precedent); contracts.ts restored to
the generated mirror; imports updated in store and AdminZone.
Refs: WP3-I3; follows Frontend PR #63.
2026-10-12 02:49:46 +00:00
weichen c1225bb880 Merge pull request 'Host plugin-declared sections in the admin zone (WP3-I3)' (#63) from feature/adminzone-plugin-sections into main 2026-10-12 02:39:56 +00:00
4 changed files with 9 additions and 11 deletions
+6 -1
View File
@@ -1,7 +1,7 @@
// API 客户端(API-first:UI 只是第一个客户端)与 SSE 流客户端(游标重放 + 终态对账)。 // API 客户端(API-first:UI 只是第一个客户端)与 SSE 流客户端(游标重放 + 终态对账)。
// 认证:服务端开启 API key 时经 auth.fetch/withKey 注入凭证(嵌入式档无认证则透传)。 // 认证:服务端开启 API key 时经 auth.fetch/withKey 注入凭证(嵌入式档无认证则透传)。
import { auth } from './auth' import { auth } from './auth'
import type { AdminZoneSection, import type {
Project, Conversation, Message, Run, Artifact, HITLCard, HITLResponse, Project, Conversation, Message, Run, Artifact, HITLCard, HITLResponse,
AgentProfile, SettingDesc, StreamEvent, StreamEventType, PlanSnapshot, TodoList, UploadInfo, PromptModule, AgentProfile, SettingDesc, StreamEvent, StreamEventType, PlanSnapshot, TodoList, UploadInfo, PromptModule,
ActivityCard, ActivityCard,
@@ -9,6 +9,11 @@ import type { AdminZoneSection,
const BASE = '' const BASE = ''
/** 管理区声明分区(WP3-I3/KTD4,backend 专属端点类型):编译插件经
* Registry.AddAdminZone 声明;入口不做前端权限合并,区内数据能力由组件
* 自身命令面 fail-closed。 */
export interface AdminZoneSection { id: string; title: string; icon?: string; desc?: string; order?: number }
async function json<T>(res: Response): Promise<T> { async function json<T>(res: Response): Promise<T> {
if (!res.ok) { if (!res.ok) {
const text = await res.text() const text = await res.text()
+1 -1
View File
@@ -9,7 +9,7 @@ import { store, useStore } from '../store'
import { EmptyState, Icon, type IconName } from '@ui' import { EmptyState, Icon, type IconName } from '@ui'
import { UsersPanel, ProfilesSection, PluginsSection, PluginWorkspacesPanel } from './adminSections' import { UsersPanel, ProfilesSection, PluginsSection, PluginWorkspacesPanel } from './adminSections'
import { RdmAuditWorkspace } from './RdmAuditWorkspace' import { RdmAuditWorkspace } from './RdmAuditWorkspace'
import type { AdminZoneSection } from '../contracts' import type { AdminZoneSection } from '../api'
interface AdminSectionDef { interface AdminSectionDef {
key: string key: string
-7
View File
@@ -288,13 +288,6 @@ export interface PluginManifest {
backend?: { mode?: 'inproc' | 'sidecar'; command?: string; args?: string[]; schemaVersion?: number }; backend?: { mode?: 'inproc' | 'sidecar'; command?: string; args?: string[]; schemaVersion?: number };
} }
// ---- 管理区声明分区(WP3-I3/KTD4)----
/** 编译插件经 Registry.AddAdminZone 声明的管理区展示分区;入口不做前端权限合并,
* 分区内数据能力由组件自身的命令面 fail-closed。 */
export interface AdminZoneSection {
id: string; title: string; icon?: string; desc?: string; order?: number;
}
export interface PluginPanel { export interface PluginPanel {
id: string; title: string; icon?: string; body: UINode[]; refreshTool?: string; id: string; title: string; icon?: string; body: UINode[]; refreshTool?: string;
} }
+2 -2
View File
@@ -1,7 +1,7 @@
// 应用状态:服务端权威(事件 + Query 对账),前端 store 是投影。 // 应用状态:服务端权威(事件 + Query 对账),前端 store 是投影。
// useSyncExternalStore 驱动;live 流式部件为会话内临时态,run 终态后由消息树对账收敛。 // useSyncExternalStore 驱动;live 流式部件为会话内临时态,run 终态后由消息树对账收敛。
import { useSyncExternalStore } from 'react' import { useSyncExternalStore } from 'react'
import { api, connectEvents } from './api' import { type AdminZoneSection, api, connectEvents } from './api'
import { applyTextDelta, applyThinkingDelta, applyToolCall, applyToolCallDelta, applyToolResult, applyToolOutput, applyArtifactCreated, applyArtifactUpdated, applyCheck, applyFinalizing, type LiveItem } from './live' import { applyTextDelta, applyThinkingDelta, applyToolCall, applyToolCallDelta, applyToolResult, applyToolOutput, applyArtifactCreated, applyArtifactUpdated, applyCheck, applyFinalizing, type LiveItem } from './live'
import { closePreviewTab, mergeOrphanPreviewTabs, openPreviewTab, previewTabsKey, type PreviewTab } from './previewtabs' import { closePreviewTab, mergeOrphanPreviewTabs, openPreviewTab, previewTabsKey, type PreviewTab } from './previewtabs'
import { deliveryRequestId, enqueueMessage, enqueueMessageFront, newQueuedMessage, promoteQueuedMessage, removeQueuedMessage, replaceQueuedText, type QueuedMessage } from './outbox' import { deliveryRequestId, enqueueMessage, enqueueMessageFront, newQueuedMessage, promoteQueuedMessage, removeQueuedMessage, replaceQueuedText, type QueuedMessage } from './outbox'
@@ -15,7 +15,7 @@ const FONT_SIZE_CHOICES: readonly FontSizeChoice[] = [13, 14, 16, 18]
export function isFontSizeChoice(value: number): value is FontSizeChoice { export function isFontSizeChoice(value: number): value is FontSizeChoice {
return (FONT_SIZE_CHOICES as readonly number[]).includes(value) return (FONT_SIZE_CHOICES as readonly number[]).includes(value)
} }
import type { AdminZoneSection, import type {
ActivityCard, ActivityCard,
AgentProfile, AgentProfile,
Artifact, Artifact,