Initial commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/** worker 读取多条同 tag 时的合并策略 */
|
||||
export type BlackboardInputMerge = "latest" | "concat";
|
||||
|
||||
export type BlackboardItem = {
|
||||
id: string;
|
||||
tag: string;
|
||||
content: string;
|
||||
source: string;
|
||||
scope?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
dependencies?: string[];
|
||||
metadata?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
/** 总管可见:无 content */
|
||||
export type BlackboardTagIndex = Pick<
|
||||
BlackboardItem,
|
||||
"id" | "tag" | "source" | "scope" | "updatedAt"
|
||||
>;
|
||||
|
||||
export type BlackboardWriteInput = {
|
||||
tag: string;
|
||||
content: string;
|
||||
source: string;
|
||||
scope?: string;
|
||||
dependencies?: string[];
|
||||
metadata?: Record<string, unknown>;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { BlackboardItem } from "../types/blackboard.js";
|
||||
import type { RuntimeSession } from "../types/runtime.js";
|
||||
|
||||
/** 磁盘上保存的 Book 绑定的 Session 快照(用于续作) */
|
||||
export type PersistedBookSession = {
|
||||
version: 1;
|
||||
sessionId: string;
|
||||
bookId: string;
|
||||
orchestratorId?: string;
|
||||
runtimeSession: RuntimeSession;
|
||||
blackboardItems: BlackboardItem[];
|
||||
messages: PersistedChatMessage[];
|
||||
savedAt: string;
|
||||
};
|
||||
|
||||
/** 与 session-manager ChatMessage 同形,独立类型避免循环依赖 */
|
||||
export type PersistedChatMessage = {
|
||||
id: string;
|
||||
role: "system" | "user";
|
||||
text: string;
|
||||
createdAt: string;
|
||||
kind?: string;
|
||||
actor?: string;
|
||||
title?: string;
|
||||
body?: string;
|
||||
thinking?: string;
|
||||
tokenUsage?: {
|
||||
totalTokens: number;
|
||||
cachedTokens?: number;
|
||||
cacheMissTokens?: number;
|
||||
caller?: string;
|
||||
model?: string;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
export type BookProject = {
|
||||
id: string;
|
||||
title: string;
|
||||
/** 用户选定或 agent 确认的 skill 包 */
|
||||
activeSkillId?: string;
|
||||
activeSkillName?: string;
|
||||
preview: string;
|
||||
sessionIds: string[];
|
||||
/** 最近一次持久化的 sessionId,用于续作 */
|
||||
activeSessionId?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
/** @deprecated 旧字段,等同 activeSkillId */
|
||||
orchestratorId?: string;
|
||||
/** @deprecated 旧字段,等同 activeSkillName */
|
||||
orchestratorName?: string;
|
||||
};
|
||||
|
||||
export type BookSummary = Pick<
|
||||
BookProject,
|
||||
| "id"
|
||||
| "title"
|
||||
| "activeSkillId"
|
||||
| "activeSkillName"
|
||||
| "preview"
|
||||
| "updatedAt"
|
||||
| "orchestratorId"
|
||||
| "orchestratorName"
|
||||
>;
|
||||
|
||||
export type SkillPackInfo = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
category: string;
|
||||
bookKind?: string;
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
/** 启动「填空题」字段定义(来自 SKILL ## 启动询问) */
|
||||
export type IntakeFieldDef = {
|
||||
id: string;
|
||||
label: string;
|
||||
required: boolean;
|
||||
};
|
||||
|
||||
/** 单字段展示状态 */
|
||||
export type IntakeFieldStatus = {
|
||||
id: string;
|
||||
label: string;
|
||||
required: boolean;
|
||||
value?: string;
|
||||
filled: boolean;
|
||||
};
|
||||
|
||||
/** 填空进度(供 Web 展示) */
|
||||
export type IntakeProgress = {
|
||||
fields: IntakeFieldStatus[];
|
||||
requiredTotal: number;
|
||||
requiredFilled: number;
|
||||
optionalTotal: number;
|
||||
optionalFilled: number;
|
||||
/** 全部必要项已填 */
|
||||
ready: boolean;
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
export type PresetPromptRole = "system" | "user" | "assistant";
|
||||
|
||||
export type PresetPromptEntry = {
|
||||
id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
role: PresetPromptRole;
|
||||
content: string;
|
||||
marker: boolean;
|
||||
sourceIdentifier: string;
|
||||
injection?: {
|
||||
position?: number;
|
||||
depth?: number;
|
||||
order?: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type PresetPromptOrderItem = {
|
||||
promptId: string;
|
||||
enabled: boolean;
|
||||
orderIndex: number;
|
||||
};
|
||||
|
||||
export type GenerationParameters = {
|
||||
temperature?: number;
|
||||
topP?: number;
|
||||
topK?: number;
|
||||
minP?: number;
|
||||
frequencyPenalty?: number;
|
||||
presencePenalty?: number;
|
||||
repetitionPenalty?: number;
|
||||
maxContextTokens?: number;
|
||||
maxOutputTokens?: number;
|
||||
stream?: boolean;
|
||||
reasoningEffort?: string;
|
||||
verbosity?: string;
|
||||
seed?: number;
|
||||
variants?: number;
|
||||
};
|
||||
|
||||
export type UnsupportedPresetSection = {
|
||||
path: string;
|
||||
reason: string;
|
||||
};
|
||||
|
||||
export type PresetPackage = {
|
||||
id: string;
|
||||
name: string;
|
||||
source: "native" | "sillytavern";
|
||||
prompts: PresetPromptEntry[];
|
||||
promptOrder: PresetPromptOrderItem[];
|
||||
generation: GenerationParameters;
|
||||
unsupported: UnsupportedPresetSection[];
|
||||
importedAt: string;
|
||||
raw?: unknown;
|
||||
};
|
||||
|
||||
export type PresetImportReport = {
|
||||
preset: PresetPackage;
|
||||
promptCount: number;
|
||||
enabledCount: number;
|
||||
unreferencedCount: number;
|
||||
missingIdentifiers: string[];
|
||||
generationFields: string[];
|
||||
warnings: string[];
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { BlackboardItem } from "./blackboard.js";
|
||||
import type { PersistedChatMessage } from "./book-session.js";
|
||||
import type { RuntimeSession } from "./runtime.js";
|
||||
|
||||
/** 实例化完成后的对象,或 run 中某一时刻的完整进度 */
|
||||
export type SnapshotKind = "instance" | "run";
|
||||
|
||||
/**
|
||||
* Book 快照(手动保存,可多档)
|
||||
* - instance:实例化后的对象(情境、规则、角色设定等),用于复用思想实验框架、换角色重跑
|
||||
* - run:运行存档,含轮次进度,读档后续玩
|
||||
*/
|
||||
export type RunSnapshot = {
|
||||
version: 1;
|
||||
id: string;
|
||||
bookId: string;
|
||||
label: string;
|
||||
kind: SnapshotKind;
|
||||
/** skill 包 id(兼容旧字段名) */
|
||||
orchestratorId?: string;
|
||||
runtimeSession: RuntimeSession;
|
||||
blackboardItems: BlackboardItem[];
|
||||
/** 保存时的对话;实例快照通常较短(到 setup 验收为止) */
|
||||
messages: PersistedChatMessage[];
|
||||
createdAt: string;
|
||||
note?: string;
|
||||
};
|
||||
|
||||
/** 列表展示用,不含正文 payload */
|
||||
export type RunSnapshotMeta = {
|
||||
id: string;
|
||||
bookId: string;
|
||||
label: string;
|
||||
kind: SnapshotKind;
|
||||
/** skill 包 id(兼容旧字段名) */
|
||||
orchestratorId?: string;
|
||||
createdAt: string;
|
||||
note?: string;
|
||||
};
|
||||
|
||||
export function toRunSnapshotMeta(snapshot: RunSnapshot): RunSnapshotMeta {
|
||||
return {
|
||||
id: snapshot.id,
|
||||
bookId: snapshot.bookId,
|
||||
label: snapshot.label,
|
||||
kind: snapshot.kind,
|
||||
orchestratorId: snapshot.orchestratorId,
|
||||
createdAt: snapshot.createdAt,
|
||||
note: snapshot.note,
|
||||
};
|
||||
}
|
||||
|
||||
export const SNAPSHOT_KIND_LABELS: Record<SnapshotKind, string> = {
|
||||
instance: "实例",
|
||||
run: "进度",
|
||||
};
|
||||
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* 运行阶段机类型契约。
|
||||
*
|
||||
* 设计原则:
|
||||
* - 运行相位(RuntimePhase)只有 5 种,表示「系统在等什么」
|
||||
* - 业务细节不扩 phase,而用 waitingReason、slots、artifacts 承载
|
||||
* - LLM / 总管不能直接改 phase,只能通过 RuntimeEvent 驱动 applyEvent
|
||||
*/
|
||||
|
||||
import type { IntakeFieldDef } from "./intake.js";
|
||||
|
||||
/** 运行相位:系统当前在等什么。只有 5 种。 */
|
||||
export type RuntimePhase =
|
||||
| "idle" // 会话已创建,尚未开始
|
||||
| "running" // 正在推进(总管决策、worker 执行、程序验收)
|
||||
| "waiting_user" // 等待用户介入
|
||||
| "done" // 流程正常结束
|
||||
| "error"; // 不可恢复错误
|
||||
|
||||
/**
|
||||
* waiting_user 时的具体原因。
|
||||
* 用单一 phase + reason 替代多个独立 status,避免「胖状态机」。
|
||||
*/
|
||||
export type WaitingReason =
|
||||
| { kind: "skill_selection"; availableSkills: SkillIndexEntry[] } // 启动:选 SKILL.md
|
||||
| { kind: "intake"; prompt: string } // 启动填空:必要/可选项收集
|
||||
| { kind: "input"; message?: string } // 总管 ask_user / 返工说明(启动完成后)
|
||||
| { kind: "approve_step"; decisionId: string } // 总管建议 run_worker,等用户确认
|
||||
| { kind: "review_artifact"; artifactId: string } // worker 产物待验收
|
||||
| { kind: "worker_questions"; workerId: string; questions: string[] } // worker 中途提问
|
||||
| { kind: "revision"; instruction?: string }; // 产物被拒或程序验收失败
|
||||
|
||||
/** 与 src/skills/types 对齐的最小 skill 索引字段,避免 runtime 强依赖 skills 模块 */
|
||||
export type SkillIndexEntry = {
|
||||
name: string;
|
||||
description: string;
|
||||
category: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Book 存储形态(由 SKILL.md 选定,选 skill 后不可变更)。
|
||||
* 第一版仅两种:小说线性结构 / 多轮多角色对话。
|
||||
*/
|
||||
export type BookKind = "novel" | "dialogue";
|
||||
|
||||
/** 选中的 skill 快照,写入 session.slots.activeSkill,供启动询问与后续流程使用 */
|
||||
export type ActiveSkillSnapshot = {
|
||||
name: string;
|
||||
description: string;
|
||||
category: string;
|
||||
/** 选定 skill 时确定,对应 Book 最终产物结构 */
|
||||
bookKind?: BookKind;
|
||||
defaultFlowId?: string;
|
||||
suggestedWorkers: string[];
|
||||
/** 来自 SKILL.md ## 启动询问 的展示文案 */
|
||||
startupPrompt: string;
|
||||
/** 用户首次输入写入的 slots 键,如 book.brief */
|
||||
startupTargetKey: string;
|
||||
/** 启动填空字段(必要 + 可选) */
|
||||
intakeFields: IntakeFieldDef[];
|
||||
};
|
||||
|
||||
/** worker 产物验收方式 */
|
||||
export type AcceptanceMode =
|
||||
| "user_confirmed" // 默认:产物完成后等用户验收
|
||||
| "no_confirmation" // 自动接受,直接回到总管
|
||||
| "programmatic_review"; // 走程序验收规则
|
||||
|
||||
/**
|
||||
* Worker 链推进模式(预留)。
|
||||
*
|
||||
* - manual:默认。每次 run_worker 可要求 approve_step;产物默认 user_confirmed。
|
||||
* - semi_auto:半自动串联 worker;仅在 skill 声明的 pauseCheckpoint 处强制暂停。
|
||||
*
|
||||
* 第一版 Runtime 仅实现 manual;semi_auto 由 orchestrator 文档化,待后续接入。
|
||||
* 见 docs/runtime-state-machine.md §10、docs/orchestrator-skill-format.md §10。
|
||||
*/
|
||||
export type WorkerAdvanceMode = "manual" | "semi_auto";
|
||||
|
||||
/**
|
||||
* semi_auto 下的暂停检查点(由各 skill 在 orchestrator 中声明)。
|
||||
*
|
||||
* `when` 为 skill 自定义的暂停条件描述或未来可解析的表达式;
|
||||
* 具体变量(轮次、token 预算、阶段界等)不由全局 enum 限定。
|
||||
*/
|
||||
export type AdvancePauseCheckpoint = {
|
||||
id: string;
|
||||
description: string;
|
||||
/** 文档化条件;未来可绑定 slot / tag / 计数器,现阶段 Runtime 不解析 */
|
||||
when?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 会话级 worker 推进策略(预留)。
|
||||
* 未设置或未解析时等价 `{ mode: "manual" }`。
|
||||
*/
|
||||
export type AdvancePolicy = {
|
||||
mode: WorkerAdvanceMode;
|
||||
pauseCheckpoints?: AdvancePauseCheckpoint[];
|
||||
};
|
||||
|
||||
/** 总管(Main Agent)可执行的意图,对应 tool call 的 action 字段 */
|
||||
export type MainAgentAction =
|
||||
| "ask_user" // 向用户提问
|
||||
| "run_worker" // 调度已有 worker
|
||||
| "create_temp_worker" // 临时 worker(与 run_worker 共用阶段机分支)
|
||||
| "review_blackboard" // 查看黑板后向用户说明
|
||||
| "finish"; // 结束流程
|
||||
|
||||
/**
|
||||
* 总管的一次决策。
|
||||
* statePatchAllowed 必须为 false,禁止 LLM 直接 patch 会话状态。
|
||||
*/
|
||||
export type MainAgentDecision = {
|
||||
id: string;
|
||||
action: MainAgentAction;
|
||||
reason: string;
|
||||
workerId?: string;
|
||||
/** 调度 role-decide 等时指定当前决策角色,Runtime 写入 世界.当前角色.id */
|
||||
workerContext?: { roleId?: string };
|
||||
/** true 时进入 waiting_user(approve_step),等用户确认后才 run_worker */
|
||||
requiresApproval: boolean;
|
||||
statePatchAllowed: false;
|
||||
};
|
||||
|
||||
/** worker 产物的生命周期状态 */
|
||||
export type ArtifactStatus =
|
||||
| "drafted"
|
||||
| "under_review"
|
||||
| "accepted"
|
||||
| "rejected"
|
||||
| "revision_requested"
|
||||
| "superseded";
|
||||
|
||||
/** worker 产出的一条产物记录 */
|
||||
export type ArtifactRecord = {
|
||||
id: string;
|
||||
workerId: string;
|
||||
stepId?: string;
|
||||
outputTags: string[];
|
||||
status: ArtifactStatus;
|
||||
summary?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
/** worker 因 ask_user 中途暂停时保存的上下文,用户回复后用于 resume_worker */
|
||||
export type ResumeContext = {
|
||||
workerId: string;
|
||||
stepId?: string;
|
||||
acceptanceMode: AcceptanceMode;
|
||||
questions: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* 阶段机唯一合法的状态变更入口。
|
||||
* 所有 phase 转移都必须通过 dispatch → applyEvent 处理某种 RuntimeEvent。
|
||||
*/
|
||||
export type RuntimeEvent =
|
||||
| {
|
||||
type: "session_started";
|
||||
payload: { presetId: string; flowId?: string; availableSkills: SkillIndexEntry[] };
|
||||
}
|
||||
| { type: "skill_selected"; payload: { skill: ActiveSkillSnapshot } }
|
||||
| {
|
||||
type: "user_submitted_input";
|
||||
payload: { text: string; intakeValues?: Record<string, string> };
|
||||
}
|
||||
| { type: "user_confirmed_intake"; payload: Record<string, never> }
|
||||
| {
|
||||
type: "main_agent_decision_created";
|
||||
payload: { decision: MainAgentDecision };
|
||||
}
|
||||
| { type: "user_approved_next_step"; payload: { decisionId: string } }
|
||||
| {
|
||||
type: "user_rejected_next_step";
|
||||
payload: { decisionId: string; reason?: string };
|
||||
}
|
||||
| {
|
||||
type: "worker_started";
|
||||
payload: {
|
||||
workerId: string;
|
||||
stepId?: string;
|
||||
acceptanceMode: AcceptanceMode;
|
||||
};
|
||||
}
|
||||
| { type: "worker_completed"; payload: { artifactId: string } }
|
||||
| {
|
||||
type: "worker_needs_input";
|
||||
payload: { workerId: string; stepId?: string; questions: string[] };
|
||||
}
|
||||
| { type: "user_accepted_artifact"; payload: { artifactId: string } }
|
||||
| {
|
||||
type: "user_rejected_artifact";
|
||||
payload: { artifactId: string; reason?: string };
|
||||
}
|
||||
| {
|
||||
type: "user_requested_revision";
|
||||
payload: { artifactId?: string; instruction: string };
|
||||
}
|
||||
| { type: "programmatic_review_started"; payload: { artifactId: string } }
|
||||
| { type: "programmatic_review_passed"; payload: { artifactId: string } }
|
||||
| {
|
||||
type: "programmatic_review_failed";
|
||||
payload: { artifactId: string; reason: string };
|
||||
}
|
||||
| { type: "flow_completed"; payload: Record<string, never> }
|
||||
| { type: "runtime_failed"; payload: { reason: string } };
|
||||
|
||||
/** 一次会话的完整运行时快照 */
|
||||
export type RuntimeSession = {
|
||||
id: string;
|
||||
phase: RuntimePhase;
|
||||
waitingReason?: WaitingReason;
|
||||
presetId: string;
|
||||
flowId?: string;
|
||||
/** 业务 flow 当前步骤(execution flow 层,与 phase 正交) */
|
||||
currentStepId?: string;
|
||||
currentWorkerId?: string;
|
||||
acceptanceMode?: AcceptanceMode;
|
||||
/** 推进策略(预留)。缺省 = manual,见 WorkerAdvanceMode */
|
||||
advancePolicy?: AdvancePolicy;
|
||||
reviewRequirements?: string[];
|
||||
resumeContext?: ResumeContext;
|
||||
/** 轻量槽位:activeSkill、book.brief、startupCompleted 等 */
|
||||
slots: Record<string, unknown>;
|
||||
artifacts: ArtifactRecord[];
|
||||
/** 待用户确认的总管决策(approve_step 时有效) */
|
||||
pendingDecision?: MainAgentDecision;
|
||||
/** 待验收的产物 id(review_artifact 时有效) */
|
||||
pendingArtifactId?: string;
|
||||
/** 已应用的 RuntimeEvent 日志,便于调试与回放 */
|
||||
history: RuntimeEvent[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* applyEvent 返回的副作用清单。
|
||||
* 纯函数 phase-machine 不执行 IO,由 phase-runtime 的 processEffects 消费。
|
||||
*/
|
||||
export type PhaseEffect =
|
||||
| { type: "invoke_main_agent" }
|
||||
| { type: "run_worker"; workerId: string; workerContext?: { roleId?: string } }
|
||||
| { type: "resume_worker" }
|
||||
| { type: "run_programmatic_review"; artifactId: string }
|
||||
| { type: "emit_message"; message: string };
|
||||
|
||||
/** applyEvent 的返回值:新会话快照 + 待处理副作用 + 可选错误 */
|
||||
export type ApplyEventResult = {
|
||||
session: RuntimeSession;
|
||||
effects: PhaseEffect[];
|
||||
error?: string;
|
||||
};
|
||||
|
||||
/** @deprecated 使用 RuntimePhase */
|
||||
export type RuntimeStatus = RuntimePhase;
|
||||
@@ -0,0 +1,61 @@
|
||||
/** 总管 tool 名称 */
|
||||
export type MainAgentToolName =
|
||||
| "read_blackboard"
|
||||
| "list_workers"
|
||||
| "list_artifacts"
|
||||
| "ask_user"
|
||||
| "run_worker"
|
||||
| "review_blackboard"
|
||||
| "finish";
|
||||
|
||||
/** 可在 tool loop 内反复调用、不改变运行相位的 tool */
|
||||
export const MAIN_AGENT_LOOP_TOOLS: MainAgentToolName[] = [
|
||||
"read_blackboard",
|
||||
"list_workers",
|
||||
"list_artifacts",
|
||||
];
|
||||
|
||||
/** 调用后应退出 loop、交给阶段机的终止 tool */
|
||||
export const MAIN_AGENT_TERMINAL_TOOLS: MainAgentToolName[] = [
|
||||
"ask_user",
|
||||
"run_worker",
|
||||
"review_blackboard",
|
||||
"finish",
|
||||
];
|
||||
|
||||
export function isMainAgentTerminalTool(name: string): name is MainAgentToolName {
|
||||
return (MAIN_AGENT_TERMINAL_TOOLS as string[]).includes(name);
|
||||
}
|
||||
|
||||
export function isMainAgentLoopTool(name: string): name is MainAgentToolName {
|
||||
return (MAIN_AGENT_LOOP_TOOLS as string[]).includes(name);
|
||||
}
|
||||
|
||||
export type ReadBlackboardParams = {
|
||||
tags: string[];
|
||||
};
|
||||
|
||||
export type ListWorkersParams = Record<string, never>;
|
||||
|
||||
export type ListArtifactsParams = Record<string, never>;
|
||||
|
||||
export type AskUserParams = {
|
||||
reason: string;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
export type RunWorkerParams = {
|
||||
workerId: string;
|
||||
reason: string;
|
||||
requiresApproval: boolean;
|
||||
roleId?: string;
|
||||
};
|
||||
|
||||
export type ReviewBlackboardParams = {
|
||||
reason: string;
|
||||
summary: string;
|
||||
};
|
||||
|
||||
export type FinishParams = {
|
||||
reason: string;
|
||||
};
|
||||
Reference in New Issue
Block a user