443 lines
18 KiB
TypeScript
443 lines
18 KiB
TypeScript
// 从 Agent-System-Core ts/types.ts 同步(make contracts 生成;Core 为权威)。
|
||
// Agent-System-Core 契约的 TypeScript 镜像。
|
||
// 线格式契约以 Go 类型(camelCase JSON 标签)与 testdata/golden/*.json 黄金样本为准;
|
||
// 本文件手工镜像同一契约,前端按未知 type/字段静默忽略(前向兼容原则)。
|
||
|
||
export type ID = string;
|
||
|
||
// ---- 领域模型 ----
|
||
|
||
export interface Project {
|
||
id: ID; owner?: ID; name: string; createdAt: string; updatedAt: string;
|
||
settings?: Record<string, unknown>;
|
||
}
|
||
|
||
export interface Conversation {
|
||
id: ID; projectId: ID; owner?: ID; title: string; profileId?: ID;
|
||
pinned?: boolean; archived?: boolean;
|
||
allowCrossRead?: boolean; crossPrivate?: boolean;
|
||
permissionMode?: 'default' | 'plan' | 'auto_edit' | '';
|
||
sessionNote?: string;
|
||
createdAt: string; updatedAt: string;
|
||
}
|
||
|
||
export type Role = 'user' | 'assistant' | 'system';
|
||
|
||
export type PartType =
|
||
| 'text' | 'thinking' | 'tool_call' | 'tool_result' | 'artifact_ref'
|
||
| 'hitl' | 'plan' | 'error' | 'card' | 'check';
|
||
|
||
export interface Part {
|
||
type: PartType;
|
||
text?: string;
|
||
toolCall?: { id: string; name: string; arguments?: string; durationMs?: number };
|
||
toolResult?: { callId: string; status: 'ok' | 'error'; summary?: string; truncated?: boolean };
|
||
artifact?: { artifactId: ID; name: string; kind?: string };
|
||
hitl?: { cardId: ID; question: string; resolved: boolean; answer?: string };
|
||
plan?: PlanSnapshot;
|
||
card?: { kind: string; data: UINode[]; cardId?: ID }; // cardId 非空 = 收件箱卡片引用部件(submit_card)
|
||
error?: { code: string; message: string };
|
||
check?: { passed: boolean; reason?: string }; // 终轮自动检查,过程区一行
|
||
process?: boolean; // run 终态后折叠为摘要行
|
||
durationMs?: number; // thinking 部件的思考时长(毫秒);工具耗时在 toolCall.durationMs
|
||
}
|
||
|
||
export interface Message {
|
||
id: ID; conversationId: ID; runId?: ID; role: Role;
|
||
parts: Part[]; createdAt: string;
|
||
excluded?: boolean;
|
||
variantGroup?: string;
|
||
variantIndex?: number;
|
||
}
|
||
|
||
export type RunKind = 'conversation' | 'subagent' | 'tool';
|
||
export type RunStatus =
|
||
| 'pending' | 'running' | 'waiting_hitl' | 'completed'
|
||
| 'failed' | 'cancelled' | 'interrupted';
|
||
export type RunPhase = 'thinking' | 'acting' | 'responding' | 'finalizing' | 'done';
|
||
|
||
export interface Usage {
|
||
promptTokens: number; completionTokens: number; totalTokens: number;
|
||
durationMs: number; toolCalls: number;
|
||
model?: string;
|
||
// N3 计费拆分(additive;旧记录缺省为 0):
|
||
// Last* 是最近一次请求的用量,Cache* 是缓存命中累计。
|
||
lastPromptTokens?: number;
|
||
lastCompletionTokens?: number;
|
||
cacheReadTokens?: number;
|
||
cacheWriteTokens?: number;
|
||
}
|
||
|
||
export interface Run {
|
||
id: ID; parentRunId?: ID; conversationId: ID; projectId: ID; owner?: ID;
|
||
kind: RunKind; profileId?: ID; status: RunStatus; phase?: RunPhase;
|
||
agentName?: string; createdAt: string; endedAt?: string;
|
||
usage?: Usage; error?: { code: string; message: string };
|
||
}
|
||
|
||
export interface Artifact {
|
||
id: ID; projectId: ID; owner?: ID; name: string; kind: string; mime?: string;
|
||
size: number; sourceRun?: ID; createdAt: string; updatedAt: string;
|
||
}
|
||
|
||
export interface PlanSnapshot {
|
||
planId: ID; title: string;
|
||
steps: { id: string; text: string; status: 'pending' | 'in_progress' | 'done' | 'skipped'; agentRun?: ID }[];
|
||
}
|
||
|
||
export interface TodoList {
|
||
conversationId: ID;
|
||
items: { id: string; text: string; status: 'pending' | 'in_progress' | 'done' }[];
|
||
}
|
||
|
||
// ---- 流式事件 ----
|
||
|
||
export type StreamEventType =
|
||
| 'message.delta' | 'thinking.delta'
|
||
| 'tool.call.delta' | 'tool.call' | 'tool.output' | 'tool.result'
|
||
| 'run.phase' | 'run.check' | 'hitl.request' | 'hitl.resolved' | 'plan.update' | 'todo.update'
|
||
| 'agent.spawn' | 'agent.progress' | 'agent.result'
|
||
| 'artifact.created' | 'artifact.updated'
|
||
| 'run.completed' | 'run.failed' | 'error'
|
||
| 'card.created' | 'card.updated' | 'card.status' | 'card.resolved'
|
||
| 'surface.updated';
|
||
|
||
export interface StreamEvent<P = unknown> {
|
||
seq: number; runId?: ID; conversationId: ID; ts: string; v: number;
|
||
type: StreamEventType; payload?: P;
|
||
}
|
||
|
||
// payload 形状(按 type 判别;未知字段忽略)
|
||
export interface MessageDeltaPayload { index: number; text: string }
|
||
export interface ToolCallDeltaPayload { index: number; callId?: string; name?: string; delta: string }
|
||
export interface ToolOutputPayload { callId: string; stream: 'stdout' | 'stderr'; text: string }
|
||
export interface ToolResultPayload { callId: string; status: string; summary?: string; truncated?: boolean; durationMs?: number }
|
||
export interface AgentSpawnPayload { agentRun: ID; name: string; task: string }
|
||
export interface AgentProgressPayload { agentRun: ID; note?: string; phase?: RunPhase }
|
||
export interface AgentResultPayload { agentRun: ID; status: RunStatus; summary?: string }
|
||
export interface HITLResolvedPayload { cardId: ID; answer?: string; kind: 'choice' | 'free' | 'timeout' | 'cancelled' }
|
||
export interface RunCompletedPayload {
|
||
usage: Usage
|
||
context?: ContextObservation
|
||
}
|
||
|
||
interface ContextSection {
|
||
name: string
|
||
estTokens: number
|
||
}
|
||
|
||
export interface ContextObservation {
|
||
items: string[]
|
||
truncations?: string[]
|
||
estChars: number
|
||
sections?: ContextSection[]
|
||
prefixHash?: string
|
||
}
|
||
export interface RunCheckPayload { passed: boolean; reason?: string }
|
||
export interface RunFailedPayload { code: string; message: string }
|
||
|
||
// ---- 收件箱卡片 ----
|
||
|
||
export type CardKind =
|
||
| 'progress' | 'confirm' | 'compare' | 'review-list'
|
||
| 'result' | 'error' | 'status';
|
||
|
||
export type CardStatus =
|
||
| 'active' | 'action_required' | 'done'
|
||
| 'resolved' | 'failed' | 'dismissed';
|
||
|
||
export interface ActivityCard {
|
||
id: ID; projectId: ID; conversationId?: ID;
|
||
sourceRunId?: ID; anchorMessageId?: ID;
|
||
kind: CardKind; title: string; status: CardStatus; tone?: string;
|
||
task?: TaskSnapshot;
|
||
body?: UINode[]; actions?: { id: string; label: string; style?: 'primary' | 'default' | 'danger'; command?: string }[];
|
||
pinned?: boolean; createdAt: string; updatedAt: string; work?: WorkCard;
|
||
}
|
||
|
||
export interface WorkCard {
|
||
result?: string; resultVersion: number; readVersion: number; completedAt?: string;
|
||
decision?: WorkDecision;
|
||
}
|
||
export interface WorkDecision {
|
||
runId?: ID;
|
||
mode: 'single' | 'multiple'; state: 'open' | 'deferred' | 'dispatching' | 'submitted';
|
||
options?: { id: string; label: string }[];
|
||
selectedIds?: string[]; freeText?: string; respondedAt?: string;
|
||
}
|
||
export interface WorkCardAction {
|
||
resultVersion: number; selectedIds?: string[]; freeText?: string;
|
||
}
|
||
|
||
export interface CardPayload { card: ActivityCard }
|
||
export interface CardStatusPayload { cardId: ID; status: CardStatus; tone?: string; note?: string }
|
||
export interface CardResolvedPayload { cardId: ID; actionId?: string; answer?: string }
|
||
|
||
// ---- HITL ----
|
||
|
||
export type HITLKind = 'choice' | 'input' | 'confirm' | 'form';
|
||
|
||
export interface HITLChoice {
|
||
id: string; label: string; description: string; impact: string; recommended?: boolean;
|
||
}
|
||
|
||
export interface HITLCard {
|
||
id: ID; runId: ID; conversationId: ID; question: string; kind: HITLKind;
|
||
choices?: HITLChoice[]; allowFreeInput: boolean; freeInputHint?: string;
|
||
timeoutSec?: number | null; form?: UINode[]; createdAt: string; resolved: boolean;
|
||
anchorMessageId?: ID; blocked?: boolean; blockReason?: string;
|
||
detail?: string;
|
||
}
|
||
|
||
export interface HITLResponse {
|
||
cardId: ID; choiceId?: string; freeText?: string; formData?: unknown;
|
||
}
|
||
|
||
// ---- UI 词汇 ----
|
||
|
||
export type UINodeType =
|
||
| 'section' | 'list' | 'kv' | 'form' | 'markdown' | 'doc-ref' | 'actions' | 'chart-lite'
|
||
| 'avatar' | 'progress' | 'compare' | 'tree' | 'table' | 'steps' | 'tabs' | 'timeline';
|
||
|
||
export interface UINode {
|
||
type: UINodeType;
|
||
/** Surface 层节点级标注(Generative UI U2):整页唯一稳定 id 与事实来源标识,旧路径不填。 */
|
||
id?: string;
|
||
source?: string[];
|
||
title?: string;
|
||
items?: string[];
|
||
kv?: [string, string][];
|
||
fields?: UIField[];
|
||
markdown?: string;
|
||
docId?: ID;
|
||
actions?: { id: string; label: string; style?: 'primary' | 'default' | 'danger' }[];
|
||
chart?: { kind: 'bar' | 'line'; labels: string[]; series: number[] };
|
||
children?: UINode[];
|
||
|
||
avatar?: { name?: string; sub?: string; tone?: string; stack?: { name?: string; sub?: string; tone?: string }[] };
|
||
progress?: { label?: string; value: number; tone?: string };
|
||
compare?: {
|
||
left: { title?: string; tone?: string; nodes?: UINode[] };
|
||
right: { title?: string; tone?: string; nodes?: UINode[] };
|
||
};
|
||
tree?: {
|
||
nodes: {
|
||
id: string; label: string; tone?: string; badge?: string; count?: number;
|
||
selected?: boolean; children?: unknown[];
|
||
}[];
|
||
};
|
||
table?: {
|
||
columns: { key: string; label: string }[];
|
||
rows: { id?: string; cells: [string, string][]; actions?: UINode['actions'] }[];
|
||
};
|
||
steps?: { current: number; steps: { label: string; status?: 'pending' | 'active' | 'done' | 'failed'; tone?: string }[] };
|
||
tabs?: { active?: string; tabs: { id: string; label: string; nodes?: UINode[] }[] };
|
||
timeline?: { items: { time?: string; title: string; tone?: string; markdown?: string; ref?: string }[] };
|
||
}
|
||
|
||
export interface UIField {
|
||
key: string; label: string;
|
||
type: 'text' | 'textarea' | 'number' | 'boolean' | 'select';
|
||
options?: string[]; required?: boolean; placeholder?: string; help?: string; default?: string;
|
||
}
|
||
|
||
// ---- 提示词库(prompt-library)----
|
||
|
||
export interface PromptTrigger {
|
||
kind: 'intent' | 'command' | 'attachment' | 'manual';
|
||
keywords?: string[]; command?: string;
|
||
}
|
||
|
||
export interface PromptModule {
|
||
id: string; layer: 'base' | 'env' | 'task' | 'agent' | 'tool' | 'aux' | 'style';
|
||
version: number; title: string; description?: string; priority?: number;
|
||
triggers?: PromptTrigger[]; requiresAttachments?: boolean;
|
||
body: string; outputContract?: string;
|
||
source?: 'builtin' | 'plugin' | 'user'; owner?: string;
|
||
basedOnVersion?: number; drifted?: boolean; disabled?: boolean;
|
||
/** 子代理 profile。只对 agent.sub.* 有意义;空字段表示沿用内置。 */
|
||
tools?: string[]; model?: string; maxTurns?: number;
|
||
}
|
||
|
||
export interface PromptBlock { moduleId: string; version: number; layer: string; body: string; }
|
||
export interface PromptHitRecord { moduleId: string; layer: string; reason: string; injected: boolean; }
|
||
|
||
// ---- 画像 / 设置 ----
|
||
|
||
export interface AgentProfile {
|
||
id: string; owner?: string; name: string; description?: string; builtin?: boolean; source?: string;
|
||
systemPrompt: string;
|
||
/** 提示词库模块引用(有序;空 = 默认 base+env 全集)。 */
|
||
promptModules?: string[];
|
||
model: { chat?: string; lightweight?: string; embedding?: string; rerank?: string };
|
||
tools: { allow: string[]; deny?: string[]; confirm?: string[] };
|
||
context: {
|
||
maxHistoryMessages: number; summarizeBeyond?: boolean;
|
||
memoryBudgetPct?: number; knowledgeBudgetPct?: number; maxToolResultChars?: number;
|
||
};
|
||
hitl: { askOnAmbiguity: boolean; timeoutSec?: number | null };
|
||
budget: { maxTokens?: number | null; maxToolCalls?: number | null; maxTurns?: number | null };
|
||
}
|
||
|
||
export interface SettingDesc {
|
||
key: string; group: string; label: string; description?: string;
|
||
type: 'string' | 'number' | 'boolean' | 'enum' | 'secret';
|
||
default?: unknown; options?: string[];
|
||
effect: 'hot' | 'new-run' | 'restart';
|
||
secret?: boolean;
|
||
/** P2 受管:system = 系统受管项,仅系统管理面可写(用户/项目层拒绝)。 */
|
||
scope?: 'system';
|
||
}
|
||
|
||
// ---- 插件 ----
|
||
|
||
export interface PluginManifest {
|
||
id: string; name: string; version: string; apiVersion: string;
|
||
requires?: { network?: string[] };
|
||
provides: {
|
||
tools?: string[]; workflows?: string[]; intents?: string[];
|
||
prompts?: string[]; panels?: string[]; cards?: string[]; settings?: string[];
|
||
commands?: string[]; workspaces?: string[];
|
||
skills?: string[]; mcpServers?: string[]; knowledge?: string[];
|
||
parsers?: string[]; agents?: string[]; channels?: string[]; pages?: string[];
|
||
};
|
||
scope?: { tenants?: string[]; projects?: string[] };
|
||
backend?: { mode?: 'inproc' | 'sidecar'; command?: string; args?: string[]; schemaVersion?: number };
|
||
}
|
||
|
||
export interface PluginPanel {
|
||
id: string; title: string; icon?: string; body: UINode[]; refreshTool?: string;
|
||
}
|
||
|
||
/** 模板占位符:{{input}}、{{slots.<key>}}、{{steps.<id>.output}}。 */
|
||
export interface WorkflowDef {
|
||
id: string; title: string; description?: string; intentId?: string;
|
||
/** 整条工作流的 critic 重试上限。 */
|
||
maxRetries?: number;
|
||
steps: WorkflowStep[];
|
||
}
|
||
|
||
export interface StepCritic {
|
||
criteria: string;
|
||
/** 本步重试上限;缺省 1 次。 */
|
||
maxRetries?: number;
|
||
}
|
||
|
||
export interface WorkflowStep {
|
||
id: string; title: string;
|
||
kind: 'prompt' | 'tool' | 'hitl' | 'artifact' | 'card' | 'script';
|
||
prompt?: string;
|
||
/** prompt 步骤的子代理 profile,缺省 general。 */
|
||
agent?: string;
|
||
tool?: string;
|
||
args?: unknown;
|
||
hitl?: { question: string; kind: HITLKind; choices?: HITLChoice[]; allowFreeInput: boolean; freeInputHint?: string };
|
||
artifact?: string;
|
||
card?: { kind: CardKind; title: string; tone?: string; body?: UINode[]; actions?: { id: string; label: string; style?: 'primary' | 'default' | 'danger'; command?: string }[] };
|
||
/** script 步骤在插件目录内的相对路径。 */
|
||
script?: string;
|
||
critic?: StepCritic;
|
||
}
|
||
|
||
export interface PluginWorkspace {
|
||
id: string; title: string; icon?: string; shortcut?: string;
|
||
badgeTool?: string; body: UINode[]; refreshTool?: string;
|
||
}
|
||
|
||
export interface PluginPageDecl {
|
||
id: string; title: string; module: string;
|
||
}
|
||
|
||
// ---- 摄取 / 检索 ----
|
||
|
||
export interface ParsedDocument {
|
||
meta: {
|
||
filename: string; mime?: string; parser: string; confidence?: number; origin?: DocumentOrigin;
|
||
crossCheck?: { with: string; diffBlocks: number; verdict: 'agree' | 'differ' };
|
||
parsedAt: string;
|
||
};
|
||
blocks: {
|
||
type: 'heading' | 'para' | 'list' | 'table' | 'code' | 'image-ref';
|
||
level?: number; text?: string; items?: string[];
|
||
rows?: string[][]; ref?: string; confidence?: number;
|
||
}[];
|
||
warnings?: string[];
|
||
}
|
||
|
||
export interface RetrievalHit {
|
||
doc: { id: ID; owner?: ID; projectId?: ID; source: string; title: string; ref?: string; chunk: string; createdAt: string };
|
||
score: number; kind: 'fulltext' | 'vector' | 'plugin';
|
||
}
|
||
|
||
export interface UploadInfo {
|
||
artifactId: ID; filename: string; mime?: string; size: number;
|
||
parsed?: ParsedDocument;
|
||
}
|
||
|
||
// ---- Generative UI Surface(提案 U2/U4;与 Go surface.go 同步)----
|
||
|
||
export interface SurfaceCompat {
|
||
schemaVersion: number;
|
||
catalogVersion: string;
|
||
pluginVersion?: string;
|
||
}
|
||
|
||
export interface SurfaceIdentity {
|
||
surfaceId: ID;
|
||
owner: string;
|
||
projectId?: ID;
|
||
conversationId?: ID;
|
||
sourceRunId?: ID;
|
||
pluginId: string;
|
||
}
|
||
|
||
export interface SurfaceSpec {
|
||
title: string;
|
||
nodes: UINode[];
|
||
}
|
||
|
||
export interface SurfaceSnapshot {
|
||
identity: SurfaceIdentity;
|
||
compat: SurfaceCompat;
|
||
revision: number;
|
||
baseRevision?: number;
|
||
contextVersion?: string;
|
||
activationEpoch: number;
|
||
spec: SurfaceSpec;
|
||
semanticText?: string;
|
||
}
|
||
|
||
export interface SurfaceMeta {
|
||
surfaceId: ID;
|
||
title: string;
|
||
pluginId: string;
|
||
revision: number;
|
||
conversationId?: ID;
|
||
updatedAt: string;
|
||
}
|
||
|
||
// Persistent work projection; host-owned identities and revisions.
|
||
export interface DocumentOrigin { artifactId: ID; contentHash: string; parserRevision: string }
|
||
export interface TaskPhase { id: string; label: string; observedAt?: string }
|
||
export interface TaskSourceRef { id: string; artifactId: ID; contentHash: string; parserRevision: string; blockIndex: number; label: string; quote?: string; availability?: string }
|
||
export interface TaskResultRef { artifactId?: ID; surfaceId?: ID; version?: string; contentHash?: string; availability: string; name?: string }
|
||
export interface TaskFinding { id: string; text: string; impact?: string; kind: string; status: string; revision: number; sources: TaskSourceRef[]; assumptions?: string; corrects?: string }
|
||
export interface TaskSnapshot {
|
||
inputs?: TaskSourceRef[]
|
||
limitations?: string[]
|
||
schemaVersion: number; taskId: ID; attemptId: ID; cardId: ID; projectId: ID; conversationId: ID;
|
||
sourceMessageId?: ID; parentRunId?: ID; runId?: ID; ownerInstanceId: string; executionEpoch?: number;
|
||
revision: number; sourceSeq: number; streamScope: string; inputRevision?: string; title: string; goal?: string;
|
||
executionState: 'queued'|'running'|'awaiting_user'|'completed'|'failed'|'interrupted'; outcomeCompleteness: 'none'|'partial'|'complete'; deliveryState: 'pending'|'available'|'reported'; phase: TaskPhase;
|
||
focus?: string; coverage?: string; remaining?: string; nextStep?: string; conclusion?: string;
|
||
findings?: TaskFinding[]; actions?: UIAction[]; resultRefs?: TaskResultRef[]; lastActivityAt?: string; lastMeaningfulUpdateAt?: string;
|
||
checkpointKeys?: Record<string,string>; checkpointCount?: number; checkpointSeq?: number;
|
||
}
|
||
export interface TaskSourceQuote { sourceId: string; blockIndex: number; quote: string }
|
||
interface WorkEvidencePremise { role: "total" | "phase" | "dependent" | "direct_relation"; sourceIndex: number; value?: number }
|
||
interface WorkFindingEvidence { mode: "direct_relation" | "difference" | "unresolved_relation"; premises: WorkEvidencePremise[]; result?: number }
|
||
export interface WorkFindingCandidate { findingKey: string; text: string; impact?: string; kind: string; assumptions?: string; corrects?: string; sources: TaskSourceQuote[]; evidence?: WorkFindingEvidence }
|
||
export interface WorkCheckpointCandidate { checkpointId: string; phaseId: string; focus?: string; remaining?: string; nextStep?: string; findings: WorkFindingCandidate[] }
|
||
|
||
export interface UIAction { id: string; label: string; style?: string; command?: string }
|