diff --git a/docs/bytemind-architecture/README.md b/docs/bytemind-architecture/README.md new file mode 100644 index 00000000..62ad2290 --- /dev/null +++ b/docs/bytemind-architecture/README.md @@ -0,0 +1,275 @@ +# bytemind 总体架构设计文档(Go 生态) + +## 1. 文档目标 +本文档定义 bytemind 的总体架构基线。 + +## 2. 既定约束 +- 单入口 TUI。 +- 会话与任务写入文件。 + +## 3. 架构目标 +- 支持 coding agent 主闭环:理解任务、调用工具、修改代码、执行验证、返回结果。 +- 支持长任务与并发:任务系统、后台执行、子代理协作。 +- 支持扩展:MCP、Skills。 +- 支持安全可控:权限分层、沙箱执行、风险拦截。 +- 支持工程治理:可恢复、可追踪、可测试。 +- 支持最小审计闭环:关键决策与关键执行可追溯、可回放 + +## 4. 架构原则 +- Secure by Default:默认最小权限,高风险操作显式确认。 +- 单一职责:原子能力优先,复杂行为通过编排组合。 +- 显式状态:关键状态可持久化、可回放、可恢复。 +- 流式优先:事件级输出,避免黑盒执行。 +- 低耦合扩展:核心稳定,扩展通过标准契约接入。 +- 可验证性:核心机制均有可执行测试与验收指标。 + +## 5. 总体架构图 +```mermaid +flowchart TB + U["用户"] + + subgraph ORCH["主编排"] + AG["agent"] + end + + subgraph STATE["会话与存储"] + SE["session"] + ST["storage"] + end + + subgraph MODEL["上下文与模型"] + CTX["context"] + PV["provider"] + end + + subgraph EXEC["安全与执行"] + PO["policy"] + TO["tools"] + RT["runtime"] + end + + U -->|提交请求| AG + AG -->|输出最终回复| U + + AG -->|读取快照| SE + AG -->|写回会话| SE + SE <--> |会话日志读写| ST + AG -->|审计事件写入| ST + + AG -->|构建上下文| CTX + CTX -->|上下文结果| AG + AG -->|发送模型请求| PV + PV -->|返回流式事件| AG + + AG -->|发起权限评估| PO + PO -->|返回决策| AG + AG -->|执行工具| TO + TO -->|返回工具事件| AG + + AG -->|提交任务/子代理| RT + RT -->|返回任务结果| AG + RT -->|任务日志写入| ST + +``` +## 6. 目录结构(Go) +```text +bytemind/ + cmd/ + bytemind/ + internal/ + core/ + app/ + agent/ + session/ + context/ + provider/ + tools/ + runtime/ + policy/ + storage/ + extensions/ +``` + +## 7. 模块职责(做什么 / 不做什么) + +### core +- 做:跨模块共享基础类型(SessionID/TaskID/Role/Decision/RiskLevel/TaskStatus)与通用错误契约。 +- 不做:业务流程、模块专属请求结构、具体实现。 + +### app +- 做:配置加载、依赖注入、生命周期管理。 +- 不做:业务编排与策略判断。 + +### agent +- 做:用户消息处理、模型交互编排、工具调用协调、结果归并。 +- 不做:工具实现细节、权限规则实现、持久化细节。 + +### session +- 做:会话创建/关闭、模式切换、会话快照与事件回放。 +- 不做:模型调用、任务调度、长期记忆。 +- 边界硬约束: +1. session 是“语义状态 owner”,storage 是“持久化正确性 owner”。 + +### context +- 做:上下文拼装、预算计算、压缩裁剪与不变量校验。 +- 不做:模型请求发送、权限判定、工具执行。 + +### provider +- 做:供应商抽象、模型路由、流式事件统一、错误语义化。 +- 不做:会话持久化、业务调度、权限判定。 + +### tools +- 做:工具 schema 校验、执行调度、事件标准化输出。 +- 不做:会话级策略决策。 + +### runtime +- 做:任务状态机、超时/取消/重试、多代理调度与归并。 +- 不做:权限规则定义。 +- 边界硬约束: +1. TaskStatus 只允许由 runtime 写入和迁移。 +2. agent 只能“发起任务/取消任务/查询任务”,不能直接改 TaskStatus。 + + +### policy +- 做:allow/deny/ask 决策、风险分级、路径/命令/敏感文件防护。 +- 不做:业务动作执行。 + +### storage +- 做:会话/任务日志写入、回放恢复、幂等去重。 +- 不做:业务决策与调度。 + +### extensions +- 做:MCP/Skills 通过统一契约接入 tools。 +- 不做:主循环控制。 + +## 8. 强制依赖约束 +- 禁止循环依赖。 +- `app` 只做装配,不承载业务逻辑。 +- `agent` 仅通过接口访问 `session/context/provider/tools/runtime/policy/storage`。 +- `extensions` 不可直接读写 `agent` 内部状态。 +- `policy` 必须可独立测试,不依赖 `agent` 具体实现。 +- 公共类型只允许放在 `core`,模块接口只放本模块特有结构。 + +## 9. 统一接口约束 +- 接口按调用方视角定义,避免泄漏实现细节。 +- 所有阻塞操作必须接收 `context.Context`。 +- 错误优先语义化(可判断、可测试)。 +- 事件流统一使用 channel/迭代器风格。 +- 接口层禁止引入具体 provider/tool 实现类型。 + +## 10. 核心执行流程 + +### 10.1 单代理主闭环 +1. 用户提交消息到 `agent`。 +2. `agent` 读取 `session` 快照。 +3. `context` 构建上下文并计算预算。 +4. `provider` 执行流式推理。 +5. 工具调用前经 `policy` 决策。 +6. `tools/runtime` 执行并返回结果事件。 +7. `storage` 写入会话/任务日志,`session` 更新状态。 +8. `agent` 返回最终响应。 + +### 10.2 自动压缩(无 Memory) +- `warning >= 85%`,`critical >= 95%`。 +- `tool_use` 与 `tool_result` 成对保留。 +- `prompt_too_long` 触发一次 reactive compact + 重试。 + +### 10.3 任务系统 +- 状态机:`pending -> running -> completed|failed|killed`。 +- 机制:超时、取消传播、最大重试次数、终态回收。 +- 输出:任务日志按 offset 增量读取。 + +### 10.4 子代理 +- 同步子代理:父代理等待返回。 +- 异步后台代理:父代理继续执行,后续归并。 +- worktree 隔离代理:独立工作区执行,避免污染主工作区。 + +## 11. Tools 体系 + +### 11.1 三层结构 +- 原子工具层:`ReadFile/EditFile/WriteFile/Glob/Grep/Bash` +- 组合工具层:`TestRunner/GitWorkflow/TaskOutputReader` +- 协作工具层:`AgentTool/MCPTool/SkillTool/TeamTool` + +### 11.2 统一契约 +```go +type Tool interface { + Name() string + Description() string + Schema() json.RawMessage + Execute(ctx context.Context, args json.RawMessage, tctx ToolUseContext) (<-chan ToolEvent, error) +} +``` + +### 11.3 强制规范 +- 参数 schema 强校验。 +- 显式声明副作用级别与幂等级别。 +- 支持超时、取消、重试语义。 +- 统一事件流:`start/chunk/result/error`。 +- 每个工具必须有 mock/contract 单测。 + +## 12. 权限与安全架构 + +### 12.1 五层权限模型 +- 会话模式层:`default/acceptEdits/bypassPermissions(受控)/plan` +- 工具白黑名单层:`allowedTools/deniedTools` +- 工具级策略层:读默认放行,写与命令默认询问 +- 风险层:`low/medium/high` +- 路径命令层:`allowedWritePaths/deniedWritePaths/allowedCommands/deniedCommands` + +### 12.2 决策优先级(固定) +`hard_deny > explicit_deny > risk_rule > explicit_allow(仅低中风险可生效) > mode_default > fallback_ask` + +### 12.3 安全基线 +- Prompt Injection:系统指令优先,工具输出隔离。 +- 路径安全:`resolve + realpath + allowlist`。 +- 命令安全:白名单 + 高危规则。 +- 敏感文件保护:密钥/凭证默认拒绝读取。 +- 沙箱策略:网络开关、路径白名单、资源限额。 + +## 13. 文件存储与恢复(不落库) + +### 13.1 文件布局 +- `~/.bytemind/sessions/.jsonl` +- `~/.bytemind/tasks/.log` +- `~/.bytemind/audit/.jsonl` + +### 13.2 一致性策略 +- append-only 写入。 +- 单记录原子落盘(`tmp+rename` 或 `fsync`)。 +- 会话级文件锁,避免并发乱序。 +- 事件携带 `event_id`,恢复时幂等去重。 +- 审计记录采用 append-only,与会话/任务日志一致的原子写策略。 +- 每条审计事件包含 `event_id/session_id/task_id/trace_id/timestamp`,启动恢复时按 `event_id` 幂等去重。 + +### 13.3 最小审计范围 +- 必记事件:`permission_decision`、`permission_ask_resolved`、`tool_execute_start`、`tool_execute_result`、`task_state_changed`。 +- 必记字段:`event_id`、`session_id`、`task_id`、`trace_id`、`actor`、`action`、`decision`、`reason_code`、`risk_level`、`result`、`latency_ms`。 +- 脱敏要求:命令参数和文件内容中的密钥/凭证必须脱敏后写入。 + +## 14. 可观测性 + +### 14.1 指标 +- 请求成功率、工具成功率、任务成功率。 +- 首字节时延(模型/工具/存储分层)。 +- token 消耗与单位任务成本。 +- 权限拒绝率与高危拦截率。 +- 压缩触发率与恢复成功率。 + +### 14.2 Trace +链路贯穿:`agent -> session -> context -> provider -> policy -> tools -> runtime -> storage` + +## 15. 测试与治理要求(强制) +- Contract Test:工具 schema、事件流一致性。 +- Replay Test:session/task 回放一致性。 +- Policy Test:规则冲突、优先级、边界样例。 +- Failure Test:超时、取消、崩溃恢复、重试风暴。 +- Sub-Agent Test:并发配额、资源争用、冲突归并。 +- 安全回归:高危命令、敏感文件、路径逃逸。 +- Audit Replay Test:基于 `audit + session/task` 可还原关键执行链路,且重复回放结果一致。 + +## 16. 主要风险与应对 +- 工具误操作风险。应对:多层权限 + 高危确认 + 沙箱。 +- 上下文膨胀风险。应对:预算器 + 自动压缩。 +- 子代理复杂度风险。应对:依赖图调度 + 配额控制 + 终态约束。 +- 文件一致性风险。应对:原子写 + 锁 + 幂等回放。 diff --git a/docs/bytemind-architecture/agent/README.md b/docs/bytemind-architecture/agent/README.md new file mode 100644 index 00000000..b725a06e --- /dev/null +++ b/docs/bytemind-architecture/agent/README.md @@ -0,0 +1,41 @@ +# agent 模块设计 + +## 1. 模块定位 +`agent` 是 coding agent 的主闭环编排层,负责请求处理、模型交互、工具协调和结果归并。 + +## 2. 职责边界 +做什么: +- 接收用户输入并读取会话快照。 +- 支持多模态消息(text/image/file/audio)进入主闭环。 +- 调用 `context` 构建模型请求并执行预算/压缩。 +- 调用 `provider` 消费流式模型事件。 +- 工具调用前走 `policy` 决策,再调度 `tools`。 +- 与 `runtime` 协作执行子代理。 + +不做什么: +- 不实现工具细节。 +- 不实现权限规则本身。 +- 不实现任务状态机与底层存储细节。 + +## 3. 对外接口 +- `Engine`:单轮主入口,处理 `TurnRequest` 并输出 `TurnEvent` 流。 +- `SessionGateway`:获取会话快照并追加 turn 结果。 +- `ContextGateway`:将输入和会话快照构建为模型请求。 +- `ModelGateway`:统一模型流式调用入口。 +- `PolicyGateway`:执行工具调用前权限决策。 +- `ToolGateway`:执行工具并返回工具结果事件流。 +- `RuntimeGateway`:创建和等待子代理任务。 +- `StorageGateway`:写入任务日志与审计事件。 + +## 4. 主闭环 +1. 读取 `session` 快照。 +2. 构建 `context`。 +3. 调用 `provider`。 +4. 工具意图先过 `policy`。 +5. 调用 `tools/runtime`。 +6. 写入 `session/storage/audit` 并返回终态。 + +## 5. 测试策略 +- 主循环契约测试:事件顺序与终态一致性。 +- 压缩测试:阈值触发与配对保留。 +- 工具编排测试:超时、取消、重试、并发上限。 diff --git a/docs/bytemind-architecture/agent/interface.go b/docs/bytemind-architecture/agent/interface.go new file mode 100644 index 00000000..a03df5ad --- /dev/null +++ b/docs/bytemind-architecture/agent/interface.go @@ -0,0 +1,163 @@ +//go:build ignore + +package agent + +import ( + "context" + "encoding/json" + "time" + + "bytemind/internal/core" +) + +type ErrorCode string + +const ( + ErrCodePromptTooLong ErrorCode = "prompt_too_long" + ErrCodeModelUnavailable ErrorCode = "model_unavailable" + ErrCodeModelStream ErrorCode = "model_stream_error" + ErrCodeToolExecute ErrorCode = "tool_execute_error" + ErrCodePermissionDenied ErrorCode = "permission_denied" + ErrCodePersistFailed ErrorCode = "persist_failed" +) + +type Message struct { + Role core.Role + Parts []core.MessagePart + Name string + ToolCallID string + CreatedAt time.Time +} + +type TurnRequest struct { + SessionID core.SessionID + TraceID core.TraceID + InputParts []core.MessagePart + MaxInputTokens int + MaxOutputTokens int + Metadata map[string]string +} + +type TurnEventType string + +const ( + TurnEventStart TurnEventType = "start" + TurnEventDelta TurnEventType = "delta" + TurnEventToolUse TurnEventType = "tool_use" + TurnEventToolOut TurnEventType = "tool_result" + TurnEventComplete TurnEventType = "complete" + TurnEventError TurnEventType = "error" +) + +type TurnEvent struct { + Type TurnEventType + TurnID string + Meta core.EventMeta + Payload json.RawMessage + ErrorCode string +} + +type ToolCall struct { + CallID string + Name string + Args json.RawMessage +} + +type PermissionDecision struct { + Decision core.Decision + ReasonCode string + RiskLevel core.RiskLevel +} + +type Engine interface { + HandleTurn(ctx context.Context, req TurnRequest) (<-chan TurnEvent, error) +} + +type SessionSnapshot struct { + SessionID core.SessionID + Mode core.SessionMode + Messages []Message + Metadata map[string]string +} + +type SessionGateway interface { + Snapshot(ctx context.Context, sessionID core.SessionID) (SessionSnapshot, error) + AppendTurn(ctx context.Context, sessionID core.SessionID, event TurnEvent) error +} + +type ContextBuildInput struct { + Request TurnRequest + Session SessionSnapshot +} + +type ModelRequest struct { + Messages []Message + ToolsSchemaJSON json.RawMessage + MaxOutputTokens int +} + +type ContextGateway interface { + Build(ctx context.Context, in ContextBuildInput) (ModelRequest, error) +} + +type ModelEvent struct { + Type string + Payload json.RawMessage +} + +type ModelGateway interface { + Stream(ctx context.Context, req ModelRequest) (<-chan ModelEvent, error) +} + +type PolicyGateway interface { + EvaluateToolUse(ctx context.Context, sessionID core.SessionID, call ToolCall) (PermissionDecision, error) +} + +type ToolResultEvent struct { + Type string + Payload json.RawMessage +} + +type ToolGateway interface { + Execute(ctx context.Context, call ToolCall, sessionID core.SessionID) (<-chan ToolResultEvent, error) +} + +type RuntimeGateway interface { + SpawnSubAgent(ctx context.Context, req SubAgentRequest) (SubAgentHandle, error) + WaitSubAgent(ctx context.Context, handle SubAgentHandle) (SubAgentResult, error) +} + +type SubAgentRequest struct { + ParentSessionID core.SessionID + ParentTaskID core.TaskID + TraceID core.TraceID + Mode core.SessionMode + Prompt string + Background bool +} + +type SubAgentHandle struct { + SubTaskID core.TaskID +} + +type SubAgentResult struct { + SubTaskID core.TaskID + Output string + ErrorCode string +} + +type AuditRecord struct { + Meta core.EventMeta + Actor string + Action string + Decision core.Decision + ReasonCode string + RiskLevel core.RiskLevel + Result string + LatencyMS int64 +} + +type StorageGateway interface { + WriteAudit(ctx context.Context, record AuditRecord) error + WriteTaskLog(ctx context.Context, taskID core.TaskID, payload json.RawMessage) error +} diff --git a/docs/bytemind-architecture/app/README.md b/docs/bytemind-architecture/app/README.md new file mode 100644 index 00000000..dee9af01 --- /dev/null +++ b/docs/bytemind-architecture/app/README.md @@ -0,0 +1,31 @@ +# app 模块设计 + +## 1. 模块定位 +`app` 是系统装配根,负责配置加载、依赖注入和进程生命周期管理。 + +## 2. 职责边界 +做什么: +- 加载并校验配置。 +- 装配 `agent/session/context/provider/tools/runtime/policy/storage/extensions`。 +- 管理启动、就绪、优雅退出。 + +不做什么: +- 不承载业务编排逻辑。 +- 不实现权限、任务、工具、存储的业务细节。 + +## 3. 对外接口 +- `ConfigLoader`:加载并归一化配置源(文件/环境变量/参数)。 +- `Component`:统一组件生命周期(`Start/Stop/Ready`)。 +- `Bootstrapper`:根据配置构建模块集合 `ModuleSet`。 +- `LifecycleManager`:按依赖拓扑启动和关闭模块。 +- `Application`:应用进程入口(`Run/Shutdown`)。 +- 配置中的会话模式复用 `core.SessionMode`,避免跨模块常量漂移。 + +## 4. 启停策略 +- 启动顺序建议:`storage -> session -> policy -> tools/extensions -> context -> provider -> runtime -> agent`。 +- 关闭顺序建议:按启动逆序关闭并刷盘。 + +## 5. 测试策略 +- 配置测试:默认值与非法配置校验。 +- 装配测试:依赖缺失与回滚完整性。 +- 生命周期测试:幂等启动/关闭、超时退出。 diff --git a/docs/bytemind-architecture/app/interface.go b/docs/bytemind-architecture/app/interface.go new file mode 100644 index 00000000..eef9fe31 --- /dev/null +++ b/docs/bytemind-architecture/app/interface.go @@ -0,0 +1,69 @@ +//go:build ignore + +package app + +import ( + "context" + + "bytemind/internal/core" +) + +type ErrorCode string + +const ( + ErrCodeInvalidConfig ErrorCode = "invalid_config" + ErrCodeBuildFailed ErrorCode = "build_failed" + ErrCodeStartFailed ErrorCode = "start_failed" + ErrCodeStopFailed ErrorCode = "stop_failed" + ErrCodeShutdownTimeout ErrorCode = "shutdown_timeout" +) + +type ConfigSource struct { + FilePath string + EnvPrefix string + Args []string + WorkingDir string +} + +type Config struct { + WorkspaceRoot string + SessionMode core.SessionMode + LogLevel string +} + +type ConfigLoader interface { + Load(ctx context.Context, source ConfigSource) (Config, error) +} + +type Component interface { + Name() string + Start(ctx context.Context) error + Stop(ctx context.Context) error + Ready() <-chan struct{} +} + +type ModuleSet struct { + Storage Component + Session Component + Policy Component + Tools Component + Extensions Component + Context Component + Provider Component + Runtime Component + Agent Component +} + +type Bootstrapper interface { + Build(ctx context.Context, cfg Config) (ModuleSet, error) +} + +type LifecycleManager interface { + Start(ctx context.Context, modules ModuleSet) error + Stop(ctx context.Context, modules ModuleSet) error +} + +type Application interface { + Run(ctx context.Context) error + Shutdown(ctx context.Context) error +} diff --git a/docs/bytemind-architecture/context/README.md b/docs/bytemind-architecture/context/README.md new file mode 100644 index 00000000..f059fcba --- /dev/null +++ b/docs/bytemind-architecture/context/README.md @@ -0,0 +1,33 @@ +# context 模块设计 + +## 1. 模块定位 +`context` 负责模型输入上下文工程:拼装、预算、压缩、约束校验。 + +## 2. 职责边界 +做什么: +- 组合系统指令、会话历史、多模态用户输入、工具 schema、运行时提示。 +- 计算 token 预算并输出预算计划。 +- 按 warning/critical/reactive 策略执行压缩。 +- 校验工具调用配对和系统约束不变量。 + +不做什么: +- 不直接请求模型。 +- 不直接写入会话存储。 +- 不执行权限判定与工具调用。 + +## 3. 对外接口 +- `Builder`:上下文构建入口,支持一次性结果与流式构建事件。 +- `Budgeter`:token 预算规划。 +- `Compactor`:上下文压缩策略执行。 +- `InvariantChecker`:压缩后语义不变量校验。 + +## 4. 关键规则 +- warning:`>= 85%`。 +- critical:`>= 95%`。 +- `prompt_too_long` 时允许一次 reactive compact + 重试。 +- 压缩后必须保留 `tool_use` / `tool_result` 成对语义。 + +## 5. 测试策略 +- 预算测试:不同模型上限下稳定。 +- 压缩测试:阈值触发、配对保留。 +- 构建测试:同输入可复现构建结果。 diff --git a/docs/bytemind-architecture/context/interface.go b/docs/bytemind-architecture/context/interface.go new file mode 100644 index 00000000..f290473d --- /dev/null +++ b/docs/bytemind-architecture/context/interface.go @@ -0,0 +1,126 @@ +//go:build ignore + +package context + +import ( + stdctx "context" + "encoding/json" + "time" + + "bytemind/internal/core" +) + +const ( + WarningBudgetThreshold = 0.85 + CriticalBudgetThreshold = 0.95 + ReactiveRetryLimit = 1 +) + +type ErrorCode string + +const ( + ErrCodeInvalidInput ErrorCode = "invalid_input" + ErrCodeBudgetExceeded ErrorCode = "budget_exceeded" + ErrCodeCompactionFailed ErrorCode = "compaction_failed" + ErrCodeInvariantViolated ErrorCode = "invariant_violated" +) + +type Message struct { + Role core.Role + Parts []core.MessagePart + Name string + ToolCallID string + CreatedAt time.Time +} + +type ToolDescriptor struct { + Name string + Description string + Schema json.RawMessage +} + +type RuntimeHint struct { + ActiveTaskID core.TaskID + TaskStatus core.TaskStatus + Metadata map[string]string +} + +type ProviderLimit struct { + ModelID string + MaxInputTokens int + MaxOutputTokens int +} + +type CompactionMode string + +const ( + CompactionWarning CompactionMode = "warning" + CompactionCritical CompactionMode = "critical" + CompactionReactive CompactionMode = "reactive" +) + +type BuildRequest struct { + SessionID core.SessionID + TraceID core.TraceID + UserInputParts []core.MessagePart + History []Message + SystemPrompts []Message + Tools []ToolDescriptor + RuntimeHints []RuntimeHint + ProviderLimits ProviderLimit + Metadata map[string]string +} + +type BuildResult struct { + Messages []Message + Tools []ToolDescriptor + InputTokens int + OutputTokens int + UsageRatio float64 + CompactApplied bool + CompactMode CompactionMode + ReactiveRetryUse int +} + +type BuildEventType string + +const ( + BuildEventStart BuildEventType = "start" + BuildEventPlan BuildEventType = "budget_plan" + BuildEventCompact BuildEventType = "compact" + BuildEventResult BuildEventType = "result" + BuildEventError BuildEventType = "error" +) + +type BuildEvent struct { + Type BuildEventType + Meta core.EventMeta + Payload json.RawMessage + ErrorCode string +} + +type BudgetPlan struct { + InputTokens int + MaxInputTokens int + UsageRatio float64 + NeedCompact bool + CompactMode CompactionMode + PreserveToolPairs bool +} + +type Builder interface { + Build(ctx stdctx.Context, req BuildRequest) (BuildResult, error) + BuildStream(ctx stdctx.Context, req BuildRequest) (<-chan BuildEvent, error) +} + +type Budgeter interface { + Plan(ctx stdctx.Context, req BuildRequest) (BudgetPlan, error) +} + +type Compactor interface { + Compact(ctx stdctx.Context, history []Message, mode CompactionMode, preserveToolPairs bool) ([]Message, error) +} + +type InvariantChecker interface { + Check(ctx stdctx.Context, messages []Message) error +} diff --git a/docs/bytemind-architecture/core/README.md b/docs/bytemind-architecture/core/README.md new file mode 100644 index 00000000..8de3d8d0 --- /dev/null +++ b/docs/bytemind-architecture/core/README.md @@ -0,0 +1,29 @@ +# core 模块设计(共享内核) + +## 1. 模块定位 +`core` 提供跨模块稳定共享的领域类型与通用错误契约,统一所有模块的基础语义。 + +## 2. 职责边界 +做什么: +- 定义跨模块复用类型:`SessionID`、`TaskID`、`EventID`、`TraceID`、`Role`、`SessionMode`、`TaskStatus`、`Decision`、`RiskLevel`。 +- 定义多模态消息载荷:`MessagePart`(text/image/file/audio)。 +- 定义统一事件元信息:`EventMeta`。 +- 提供通用错误语义契约:`SemanticError`。 + +不做什么: +- 不定义模块专属业务请求/响应结构。 +- 不定义业务流程编排接口。 +- 不依赖任何业务模块实现。 + +## 3. 对外接口(契约) +- `EventMeta`:所有流式事件共享元字段(`event_id/trace_id/session_id/task_id/timestamp`)。 +- `SemanticError`:错误可判定、可测试的最小接口(`Code()`、`Retryable()`)。 + +## 4. 架构对齐点 +- `SessionMode` 在 `core` 定义,避免 `session/policy/app` 重复声明。 +- `TaskStatus` 统一定义在 `core`,但迁移权仅属于 `runtime`。 +- 任何被两个及以上模块复用的基础类型必须下沉到 `core`。 + +## 5. 测试策略 +- 类型稳定性检查:常量值变更需要显式评审。 +- 错误语义检查:`SemanticError` 的 `Code/Retryable` 在上层可稳定断言。 diff --git a/docs/bytemind-architecture/core/interface.go b/docs/bytemind-architecture/core/interface.go new file mode 100644 index 00000000..6b8afdb5 --- /dev/null +++ b/docs/bytemind-architecture/core/interface.go @@ -0,0 +1,90 @@ +//go:build ignore + +package core + +import "time" + +type SessionID string +type TaskID string +type EventID string +type TraceID string + +type Role string + +const ( + RoleSystem Role = "system" + RoleUser Role = "user" + RoleAssistant Role = "assistant" + RoleTool Role = "tool" +) + +type MessagePartType string + +const ( + PartText MessagePartType = "text" + PartImage MessagePartType = "image" + PartFile MessagePartType = "file" + PartAudio MessagePartType = "audio" +) + +// MessagePart is the shared multimodal payload unit. +// Text part uses Text; media part uses URI/MIMEType/Name. +type MessagePart struct { + Type MessagePartType + Text string + URI string + MIMEType string + Name string + Metadata map[string]string +} + +type SessionMode string + +const ( + SessionModeDefault SessionMode = "default" + SessionModeAcceptEdits SessionMode = "acceptEdits" + SessionModeBypassPermissions SessionMode = "bypassPermissions" + SessionModePlan SessionMode = "plan" +) + +type TaskStatus string + +const ( + TaskPending TaskStatus = "pending" + TaskRunning TaskStatus = "running" + TaskCompleted TaskStatus = "completed" + TaskFailed TaskStatus = "failed" + TaskKilled TaskStatus = "killed" +) + +type Decision string + +const ( + DecisionAllow Decision = "allow" + DecisionDeny Decision = "deny" + DecisionAsk Decision = "ask" +) + +type RiskLevel string + +const ( + RiskLow RiskLevel = "low" + RiskMedium RiskLevel = "medium" + RiskHigh RiskLevel = "high" +) + +// EventMeta is the shared envelope carried by every stream event. +type EventMeta struct { + EventID EventID + TraceID TraceID + SessionID SessionID + TaskID TaskID + Timestamp time.Time +} + +// SemanticError is the shared minimum contract for testable errors. +type SemanticError interface { + error + Code() string + Retryable() bool +} diff --git a/docs/bytemind-architecture/extensions/README.md b/docs/bytemind-architecture/extensions/README.md new file mode 100644 index 00000000..e88238bd --- /dev/null +++ b/docs/bytemind-architecture/extensions/README.md @@ -0,0 +1,33 @@ +# extensions 模块设计 + +## 1. 模块定位 +`extensions` 是外部能力接入层,负责将 MCP/Skills 通过统一契约桥接到 `tools`。 + +## 2. 职责边界 +做什么: +- 发现、加载、卸载扩展。 +- 校验扩展元数据、版本兼容与能力声明。 +- 将扩展能力映射为标准工具并注册到 `tools`。 +- 维护扩展健康状态和故障隔离。 +- 统一桥接 MCP 与 Skills 两类扩展。 + +不做什么: +- 不直接读写 `agent` 内部状态。 +- 不承担主循环控制和权限定义。 + +## 3. 对外接口 +- `Extension`:扩展生命周期契约(激活/停用/健康检查)。 +- `ExtensionTool`:扩展暴露的工具执行契约。 +- `ToolProvider`:获取扩展提供的工具集合。 +- `Manager`:扩展加载、卸载、查询管理。 +- `Resolver`:扩展能力到工具集合的解析器。 + +## 4. 生命周期流程 +1. 发现扩展。 +2. 校验元数据。 +3. 激活并桥接工具。 +4. 健康检查。 +5. 异常降级或卸载回滚。 + +## 5. 测试策略 +- 契约映射测试、生命周期测试、安全边界测试。 diff --git a/docs/bytemind-architecture/extensions/interface.go b/docs/bytemind-architecture/extensions/interface.go new file mode 100644 index 00000000..400f8acc --- /dev/null +++ b/docs/bytemind-architecture/extensions/interface.go @@ -0,0 +1,110 @@ +//go:build ignore + +package extensions + +import ( + "context" + "encoding/json" + "time" + + "bytemind/internal/core" +) + +type ExtensionKind string + +const ( + ExtensionMCP ExtensionKind = "mcp" + ExtensionSkill ExtensionKind = "skill" +) + +type ExtensionStatus string + +const ( + StatusLoaded ExtensionStatus = "loaded" + StatusActive ExtensionStatus = "active" + StatusDegraded ExtensionStatus = "degraded" + StatusStopped ExtensionStatus = "stopped" +) + +type ErrorCode string + +const ( + ErrCodeInvalidManifest ErrorCode = "invalid_manifest" + ErrCodeIncompatible ErrorCode = "incompatible_version" + ErrCodeLoadFailed ErrorCode = "load_failed" + ErrCodeActivateFailed ErrorCode = "activate_failed" + ErrCodeToolBridge ErrorCode = "tool_bridge_failed" +) + +type Manifest struct { + ID string + Name string + Kind ExtensionKind + Version string + Description string + Entry string + UpdatedAt time.Time +} + +type Capability struct { + Name string + Description string + SideEffects []string +} + +type ExtensionInfo struct { + Manifest Manifest + Status ExtensionStatus + Capabilities []Capability +} + +type ActivateOptions struct { + WorkspaceRoot string + ConfigPath string + Env map[string]string +} + +type Extension interface { + Info() ExtensionInfo + Activate(ctx context.Context, opts ActivateOptions) error + Deactivate(ctx context.Context) error + Health(ctx context.Context) (ExtensionStatus, error) +} + +type ToolUseContext struct { + SessionID core.SessionID + TaskID core.TaskID + TraceID core.TraceID + Workspace string + Metadata map[string]string +} + +type ToolEvent struct { + Type string + CallID string + Meta core.EventMeta + Payload json.RawMessage + ErrorCode string +} + +type ExtensionTool interface { + Name() string + Description() string + Schema() json.RawMessage + Execute(ctx context.Context, args json.RawMessage, tctx ToolUseContext) (<-chan ToolEvent, error) +} + +type ToolProvider interface { + Tools(ctx context.Context) ([]ExtensionTool, error) +} + +type Manager interface { + Load(ctx context.Context, source string) (ExtensionInfo, error) + Unload(ctx context.Context, extensionID string) error + List(ctx context.Context) ([]ExtensionInfo, error) + Get(ctx context.Context, extensionID string) (ExtensionInfo, bool, error) +} + +type Resolver interface { + ResolveTools(ctx context.Context, extensionID string) ([]ExtensionTool, error) +} diff --git a/docs/bytemind-architecture/policy/README.md b/docs/bytemind-architecture/policy/README.md new file mode 100644 index 00000000..d69e5711 --- /dev/null +++ b/docs/bytemind-architecture/policy/README.md @@ -0,0 +1,37 @@ +# policy 模块设计 + +## 1. 模块定位 +`policy` 是权限与安全决策中心,输出 `allow/deny/ask` 及风险等级。 + +## 2. 职责边界 +做什么: +- 执行五层权限模型。 +- 按固定优先级处理规则冲突。 +- 进行路径、命令、敏感文件风险判定。 + +不做什么: +- 不执行业务动作。 +- 不承担主循环和任务调度。 + +## 3. 对外接口 +- `Engine`:策略决策主入口。 +- `Rule`:按阶段归属的可组合原子规则。 +- `RuleSet`:规则注册与枚举。 +- `PriorityResolver`:固定优先级决策归并器。 +- `PathGuard`:路径访问安全判定。 +- `CommandGuard`:命令执行安全判定。 +- `SensitiveFileGuard`:敏感文件读取防护。 + +## 4. 决策优先级 +`hard_deny > explicit_deny > risk_rule > explicit_allow(仅低中风险可生效) > mode_default > fallback_ask` + +## 5. 五层权限模型 +- 会话模式层:`default/acceptEdits/bypassPermissions(受控)/plan`。 +- 工具白黑名单层:`allowedTools/deniedTools`。 +- 工具级策略层:读默认放行,写与命令默认询问。 +- 风险层:`low/medium/high`。 +- 路径命令层:`allowedWritePaths/deniedWritePaths/allowedCommands/deniedCommands`。 + +## 6. 测试策略 +- 冲突优先级与边界样例。 +- 高危命令、敏感文件、路径逃逸回归。 diff --git a/docs/bytemind-architecture/policy/interface.go b/docs/bytemind-architecture/policy/interface.go new file mode 100644 index 00000000..871f6f66 --- /dev/null +++ b/docs/bytemind-architecture/policy/interface.go @@ -0,0 +1,108 @@ +//go:build ignore + +package policy + +import ( + "context" + + "bytemind/internal/core" +) + +type OperationKind string + +const ( + OpRead OperationKind = "read" + OpWrite OperationKind = "write" + OpExec OperationKind = "exec" + OpNet OperationKind = "network" + OpSpawn OperationKind = "spawn_agent" + OpCustom OperationKind = "custom" +) + +type DecisionStage string + +const ( + StageHardDeny DecisionStage = "hard_deny" + StageExplicitDeny DecisionStage = "explicit_deny" + StageRiskRule DecisionStage = "risk_rule" + StageExplicitAllow DecisionStage = "explicit_allow" + StageModeDefault DecisionStage = "mode_default" + StageFallbackAsk DecisionStage = "fallback_ask" +) + +type ToolPolicy struct { + AllowedTools []string + DeniedTools []string +} + +type PathCommandPolicy struct { + AllowedWritePaths []string + DeniedWritePaths []string + AllowedCommands []string + DeniedCommands []string +} + +type PermissionRequest struct { + SessionID core.SessionID + TaskID core.TaskID + TraceID core.TraceID + SessionMode core.SessionMode + ToolName string + Operation OperationKind + TargetPaths []string + Command string + Arguments []string + RequestedBy string + ToolPolicy ToolPolicy + PathPolicy PathCommandPolicy + Metadata map[string]string +} + +type PermissionDecision struct { + Decision core.Decision + ReasonCode string + RiskLevel core.RiskLevel + Stage DecisionStage + RequireUserConfirm bool + CanBypassWithSession bool +} + +type ErrorCode string + +const ( + ErrCodeInvalidRequest ErrorCode = "invalid_request" + ErrCodeRuleConflict ErrorCode = "rule_conflict" + ErrCodeRuleNotFound ErrorCode = "rule_not_found" +) + +type Engine interface { + Evaluate(ctx context.Context, req PermissionRequest) (PermissionDecision, error) +} + +type Rule interface { + Name() string + Stage() DecisionStage + Evaluate(ctx context.Context, req PermissionRequest) (PermissionDecision, bool, error) +} + +type RuleSet interface { + Register(ctx context.Context, rule Rule) error + List(ctx context.Context) ([]Rule, error) +} + +type PriorityResolver interface { + Order() []DecisionStage + Resolve(ctx context.Context, candidates []PermissionDecision) (PermissionDecision, error) +} + +type PathGuard interface { + CheckPaths(ctx context.Context, req PermissionRequest) (PermissionDecision, error) +} + +type CommandGuard interface { + CheckCommand(ctx context.Context, req PermissionRequest) (PermissionDecision, error) +} + +type SensitiveFileGuard interface { + CheckSensitiveRead(ctx context.Context, req PermissionRequest) (PermissionDecision, error) +} diff --git a/docs/bytemind-architecture/provider/README.md b/docs/bytemind-architecture/provider/README.md new file mode 100644 index 00000000..bc992563 --- /dev/null +++ b/docs/bytemind-architecture/provider/README.md @@ -0,0 +1,33 @@ +# provider 模块设计 + +## 1. 模块定位 +`provider` 是模型供应商抽象层,对上提供统一流式推理能力。 + +## 2. 职责边界 +做什么: +- 管理 provider 客户端注册与模型目录。 +- 路由选择 provider/model。 +- 执行流式模型调用并统一事件语义(支持多模态消息)。 +- 归一化供应商错误(鉴权、限流、超时、不可用)。 + +不做什么: +- 不负责会话持久化。 +- 不负责权限决策。 +- 不负责工具编排。 + +## 3. 对外接口 +- `Client`:单个 provider 的统一调用契约(模型列表 + 流式推理)。 +- `Registry`:provider 注册与查询。 +- `Router`:按策略选择 provider/model,并提供降级候选。 +- `HealthChecker`:provider 健康探测。 + +## 4. 失败处理 +- 限流/超时:可重试错误。 +- 鉴权失败:不可重试错误。 +- 模型不可用:允许路由降级。 +- 统一流式事件必须携带 `event_id/trace_id` 元信息,便于链路追踪与回放。 + +## 5. 测试策略 +- 契约测试:多 provider 事件语义一致。 +- 故障测试:401/429/超时/连接中断。 +- 压测:并发流式请求的首字节与吞吐。 diff --git a/docs/bytemind-architecture/provider/interface.go b/docs/bytemind-architecture/provider/interface.go new file mode 100644 index 00000000..1bb49568 --- /dev/null +++ b/docs/bytemind-architecture/provider/interface.go @@ -0,0 +1,111 @@ +//go:build ignore + +package provider + +import ( + "context" + "encoding/json" + "time" + + "bytemind/internal/core" +) + +type ProviderID string +type ModelID string + +type ErrorCode string + +const ( + ErrCodeUnauthorized ErrorCode = "unauthorized" + ErrCodeRateLimited ErrorCode = "rate_limited" + ErrCodeTimeout ErrorCode = "timeout" + ErrCodeUnavailable ErrorCode = "unavailable" + ErrCodeBadRequest ErrorCode = "bad_request" +) + +type Message struct { + Role core.Role + Parts []core.MessagePart + Name string + ToolCallID string +} + +type ToolSpec struct { + Name string + Description string + Schema json.RawMessage +} + +type Request struct { + SessionID core.SessionID + TraceID core.TraceID + ModelID ModelID + Messages []Message + Tools []ToolSpec + MaxOutputTokens int + Temperature float64 + Metadata map[string]string +} + +type EventType string + +const ( + EventStart EventType = "start" + EventDelta EventType = "delta" + EventToolCall EventType = "tool_call" + EventUsage EventType = "usage" + EventResult EventType = "result" + EventError EventType = "error" +) + +type Usage struct { + InputTokens int + OutputTokens int + TotalTokens int + CostUSD float64 +} + +type Event struct { + Type EventType + Meta core.EventMeta + Payload json.RawMessage + Usage *Usage + ErrorCode string + Retryable bool +} + +type ModelInfo struct { + ProviderID ProviderID + ModelID ModelID + DisplayName string + MaxInputTokens int + MaxOutputTokens int + SupportsTools bool + UpdatedAt time.Time +} + +type RouteResult struct { + ProviderID ProviderID + ModelID ModelID + Fallbacks []ModelID +} + +type Client interface { + ProviderID() ProviderID + ListModels(ctx context.Context) ([]ModelInfo, error) + Stream(ctx context.Context, req Request) (<-chan Event, error) +} + +type Registry interface { + Register(ctx context.Context, client Client) error + Get(ctx context.Context, id ProviderID) (Client, bool) + List(ctx context.Context) ([]ProviderID, error) +} + +type Router interface { + Route(ctx context.Context, requestedModel ModelID, metadata map[string]string) (RouteResult, error) +} + +type HealthChecker interface { + Check(ctx context.Context, id ProviderID) error +} diff --git a/docs/bytemind-architecture/runtime/README.md b/docs/bytemind-architecture/runtime/README.md new file mode 100644 index 00000000..e2848379 --- /dev/null +++ b/docs/bytemind-architecture/runtime/README.md @@ -0,0 +1,34 @@ +# runtime 模块设计 + +## 1. 模块定位 +`runtime` 是任务与并发执行内核,负责任务状态机、多代理调度和日志增量读取。 + +## 2. 职责边界 +做什么: +- 管理任务状态机:`pending -> running -> completed|failed|killed`。 +- 处理超时、取消传播、最大重试、终态回收。 +- 调度同步/异步子代理与 worktree 隔离执行。 +- 管理并发配额和资源争用。 +- 作为 `TaskStatus` 唯一写入与迁移 owner。 + +不做什么: +- 不定义权限策略。 +- 不实现模型主循环。 +- 不处理存储落盘细节。 + +## 3. 对外接口 +- `TaskManager`:任务提交、查询、取消、重试、事件流订阅。 +- `Scheduler`:任务排队、暂停、恢复。 +- `LogReader`:任务日志按 offset 增量读取。 +- `SubAgentCoordinator`:子代理创建、等待、后台结果收集。 +- `QuotaManager`:并发配额申请与释放。 + +## 4. 多代理模式 +- 同步子代理:父任务阻塞等待。 +- 异步子代理:父任务继续执行,后续归并。 +- worktree 隔离:子任务独立工作区执行。 + +## 5. 测试策略 +- 状态机测试:合法/非法迁移。 +- 并发测试:配额、公平性、争用。 +- 失败测试:超时、取消、重试、崩溃恢复。 diff --git a/docs/bytemind-architecture/runtime/interface.go b/docs/bytemind-architecture/runtime/interface.go new file mode 100644 index 00000000..7cbc0e32 --- /dev/null +++ b/docs/bytemind-architecture/runtime/interface.go @@ -0,0 +1,111 @@ +//go:build ignore + +package runtime + +import ( + "context" + "time" + + "bytemind/internal/core" +) + +type ErrorCode string + +const ( + ErrCodeInvalidTransition ErrorCode = "invalid_transition" + ErrCodeTaskNotFound ErrorCode = "task_not_found" + ErrCodeTaskTimeout ErrorCode = "task_timeout" + ErrCodeTaskCanceled ErrorCode = "task_canceled" + ErrCodeRetryExhausted ErrorCode = "retry_exhausted" + ErrCodeQuotaExceeded ErrorCode = "quota_exceeded" +) + +type TaskSpec struct { + SessionID core.SessionID + TraceID core.TraceID + Name string + Kind string + Input []byte + ParentTaskID core.TaskID + Timeout time.Duration + MaxRetries int + Background bool + IsolatedWorktree bool + Metadata map[string]string +} + +type Task struct { + ID core.TaskID + Spec TaskSpec + Status core.TaskStatus + Attempt int + CreatedAt time.Time + StartedAt *time.Time + FinishedAt *time.Time + ErrorCode string +} + +type TaskResult struct { + TaskID core.TaskID + Status core.TaskStatus + Output []byte + ErrorCode string + FinishedAt time.Time +} + +type TaskLogEntry struct { + TaskID core.TaskID + Offset int64 + Level string + Message string + Meta core.EventMeta +} + +type TaskEventType string + +const ( + TaskEventStatus TaskEventType = "status" + TaskEventLog TaskEventType = "log" + TaskEventResult TaskEventType = "result" + TaskEventError TaskEventType = "error" +) + +type TaskEvent struct { + Type TaskEventType + TaskID core.TaskID + Status core.TaskStatus + Log *TaskLogEntry + Result *TaskResult + Meta core.EventMeta + ErrorCode string +} + +type TaskManager interface { + Submit(ctx context.Context, spec TaskSpec) (core.TaskID, error) + Get(ctx context.Context, id core.TaskID) (Task, error) + Cancel(ctx context.Context, id core.TaskID, reason string) error + Retry(ctx context.Context, id core.TaskID) (core.TaskID, error) + Wait(ctx context.Context, id core.TaskID) (TaskResult, error) + Stream(ctx context.Context, id core.TaskID) (<-chan TaskEvent, error) +} + +type Scheduler interface { + Enqueue(ctx context.Context, id core.TaskID) error + Pause(ctx context.Context, id core.TaskID) error + Resume(ctx context.Context, id core.TaskID) error +} + +type LogReader interface { + ReadIncrement(ctx context.Context, id core.TaskID, fromOffset int64, limit int) ([]TaskLogEntry, int64, error) +} + +type SubAgentCoordinator interface { + Spawn(ctx context.Context, parent core.TaskID, spec TaskSpec) (core.TaskID, error) + Wait(ctx context.Context, id core.TaskID) (TaskResult, error) + CollectBackground(ctx context.Context, parent core.TaskID) ([]TaskResult, error) +} + +type QuotaManager interface { + Acquire(ctx context.Context, key string, n int) error + Release(ctx context.Context, key string, n int) error +} diff --git a/docs/bytemind-architecture/session/README.md b/docs/bytemind-architecture/session/README.md new file mode 100644 index 00000000..52edc14e --- /dev/null +++ b/docs/bytemind-architecture/session/README.md @@ -0,0 +1,33 @@ +# session 模块设计 + +## 1. 模块定位 +`session` 负责会话生命周期、会话模式、会话快照与回放能力。 + +## 2. 职责边界 +做什么: +- 创建、读取、关闭会话。 +- 管理会话模式(default/acceptEdits/bypassPermissions/plan)。 +- 记录多模态 turn 历史与会话元信息。 +- 提供快照与事件流读取。 +- 维护“语义状态 owner”职责。 + +不做什么: +- 不调用模型。 +- 不执行工具。 +- 不承担权限决策。 +- 不承担持久化原子性与文件锁正确性(由 `storage` 负责)。 + +## 3. 对外接口 +- `Manager`:会话写操作入口(创建、模式切换、追加 turn、任务绑定、关闭)。 +- `Reader`:会话读操作入口(快照读取、增量读取、回放)。 + +## 4. 一致性策略 +- append-only 写入。 +- 会话级串行锁避免乱序。 +- 基于 `event_id` 去重,支持幂等回放。 +- 会话模式统一复用 `core.SessionMode`,避免多处定义漂移。 + +## 5. 测试策略 +- 生命周期测试:创建/关闭幂等。 +- 并发测试:多 turn 追加顺序一致。 +- 回放测试:快照重建一致。 diff --git a/docs/bytemind-architecture/session/interface.go b/docs/bytemind-architecture/session/interface.go new file mode 100644 index 00000000..fa75096b --- /dev/null +++ b/docs/bytemind-architecture/session/interface.go @@ -0,0 +1,101 @@ +//go:build ignore + +package session + +import ( + "context" + "time" + + "bytemind/internal/core" +) + +type SessionStatus string + +const ( + StatusActive SessionStatus = "active" + StatusClosing SessionStatus = "closing" + StatusClosed SessionStatus = "closed" +) + +type ErrorCode string + +const ( + ErrCodeSessionNotFound ErrorCode = "session_not_found" + ErrCodeSessionClosed ErrorCode = "session_closed" + ErrCodeInvalidMode ErrorCode = "invalid_mode" + ErrCodeReplayFailed ErrorCode = "replay_failed" +) + +type Message struct { + ID string + Role core.Role + Parts []core.MessagePart + Name string + ToolCallID string + CreatedAt time.Time +} + +type TurnRecord struct { + TurnID string + Input Message + Outputs []Message + StartedAt time.Time + EndedAt time.Time +} + +type UsageStat struct { + InputTokens int64 + OutputTokens int64 + TotalRequests int64 +} + +type SessionSnapshot struct { + ID core.SessionID + Mode core.SessionMode + Status SessionStatus + Messages []Message + Usage UsageStat + ActiveTasks []core.TaskID + Metadata map[string]string + CreatedAt time.Time + LastActiveAt time.Time +} + +type SessionEventType string + +const ( + SessionEventCreated SessionEventType = "created" + SessionEventMode SessionEventType = "mode_changed" + SessionEventTurn SessionEventType = "turn_appended" + SessionEventClosed SessionEventType = "closed" + SessionEventError SessionEventType = "error" +) + +type SessionEvent struct { + Type SessionEventType + Meta core.EventMeta + Offset int64 + Payload []byte + ErrorCode string +} + +type CreateRequest struct { + Mode core.SessionMode + Metadata map[string]string +} + +type Manager interface { + Create(ctx context.Context, req CreateRequest) (SessionSnapshot, error) + Get(ctx context.Context, id core.SessionID) (SessionSnapshot, error) + SwitchMode(ctx context.Context, id core.SessionID, mode core.SessionMode) error + AppendTurn(ctx context.Context, id core.SessionID, turn TurnRecord) error + AttachTask(ctx context.Context, id core.SessionID, taskID core.TaskID) error + DetachTask(ctx context.Context, id core.SessionID, taskID core.TaskID) error + Close(ctx context.Context, id core.SessionID, reason string) error +} + +type Reader interface { + Snapshot(ctx context.Context, id core.SessionID) (SessionSnapshot, error) + ReadEvents(ctx context.Context, id core.SessionID, fromOffset int64, limit int) ([]SessionEvent, int64, error) + Replay(ctx context.Context, id core.SessionID, fromOffset int64) (<-chan SessionEvent, error) +} diff --git a/docs/bytemind-architecture/storage/README.md b/docs/bytemind-architecture/storage/README.md new file mode 100644 index 00000000..80d0245c --- /dev/null +++ b/docs/bytemind-architecture/storage/README.md @@ -0,0 +1,34 @@ +# storage 模块设计 + +## 1. 模块定位 +`storage` 是无数据库场景下的文件持久化与恢复层,提供会话与任务日志可靠读写和回放。 + +## 2. 职责边界 +做什么: +- 写入会话事件:`~/.bytemind/sessions/.jsonl`。 +- 写入任务日志:`~/.bytemind/tasks/.log`。 +- 写入审计日志:`~/.bytemind/audit/.jsonl`。 +- 支持增量读取、回放恢复、幂等去重。 + +不做什么: +- 不做业务决策与调度。 +- 不承担权限规则与工具编排。 + +## 3. 对外接口 +- `SessionStore`:会话事件追加与增量读取。 +- `TaskStore`:任务日志追加与增量读取。 +- `AuditStore`:审计事件追加与按日增量读取。 +- `Locker`:会话/任务级锁控制。 +- `Deduplicator`:基于 `event_id` 去重。 +- `Replayer`:会话/任务/审计事件流回放。 + +## 4. 一致性策略 +- append-only。 +- 单记录原子落盘(tmp+rename 或 fsync)。 +- 文件锁避免并发乱序。 +- 审计事件与会话/任务事件统一遵循原子写入语义。 +- 审计最小字段覆盖:`event_id/session_id/task_id/trace_id/actor/action/decision/reason_code/risk_level/result/latency_ms`。 + +## 5. 测试策略 +- 原子写测试、并发写测试、去重测试、回放一致性测试。 +- 审计回放测试:基于 `audit + session/task` 可还原关键执行链路。 diff --git a/docs/bytemind-architecture/storage/interface.go b/docs/bytemind-architecture/storage/interface.go new file mode 100644 index 00000000..a50a86fd --- /dev/null +++ b/docs/bytemind-architecture/storage/interface.go @@ -0,0 +1,82 @@ +//go:build ignore + +package storage + +import ( + "context" + "time" + + "bytemind/internal/core" +) + +type ErrorCode string + +const ( + ErrCodeNotFound ErrorCode = "not_found" + ErrCodeConflict ErrorCode = "conflict" + ErrCodeCorruptedRecord ErrorCode = "corrupted_record" + ErrCodeWriteFailed ErrorCode = "write_failed" + ErrCodeReadFailed ErrorCode = "read_failed" + ErrCodeLockTimeout ErrorCode = "lock_timeout" +) + +type SessionEvent struct { + Meta core.EventMeta + Offset int64 + Type string + Payload []byte +} + +type TaskLogRecord struct { + Meta core.EventMeta + Offset int64 + Level string + Message string + Payload []byte +} + +type AuditEvent struct { + Meta core.EventMeta + Actor string + Action string + Decision core.Decision + ReasonCode string + RiskLevel core.RiskLevel + Result string + LatencyMS int64 + Payload []byte +} + +type SessionStore interface { + Append(ctx context.Context, event SessionEvent) error + ReadFrom(ctx context.Context, sessionID core.SessionID, offset int64, limit int) ([]SessionEvent, int64, error) +} + +type TaskStore interface { + AppendLog(ctx context.Context, record TaskLogRecord) error + ReadLogFrom(ctx context.Context, taskID core.TaskID, offset int64, limit int) ([]TaskLogRecord, int64, error) +} + +type AuditStore interface { + Append(ctx context.Context, event AuditEvent) error + ReadFrom(ctx context.Context, day time.Time, offset int64, limit int) ([]AuditEvent, int64, error) +} + +type Locker interface { + LockSession(ctx context.Context, sessionID core.SessionID) (UnlockFunc, error) + LockTask(ctx context.Context, taskID core.TaskID) (UnlockFunc, error) + LockAuditDay(ctx context.Context, day time.Time) (UnlockFunc, error) +} + +type UnlockFunc func() error + +type Deduplicator interface { + Seen(ctx context.Context, stream string, eventID core.EventID) (bool, error) + Mark(ctx context.Context, stream string, eventID core.EventID) error +} + +type Replayer interface { + ReplaySession(ctx context.Context, sessionID core.SessionID, fromOffset int64) (<-chan SessionEvent, error) + ReplayTask(ctx context.Context, taskID core.TaskID, fromOffset int64) (<-chan TaskLogRecord, error) + ReplayAudit(ctx context.Context, day time.Time, fromOffset int64) (<-chan AuditEvent, error) +} diff --git a/docs/bytemind-architecture/tools/README.md b/docs/bytemind-architecture/tools/README.md new file mode 100644 index 00000000..fc8d96db --- /dev/null +++ b/docs/bytemind-architecture/tools/README.md @@ -0,0 +1,34 @@ +# tools 模块设计 + +## 1. 模块定位 +`tools` 是统一工具执行平面,负责工具契约、参数校验、执行调度和标准事件流输出。 + +## 2. 职责边界 +做什么: +- 注册与发现工具。 +- 执行 schema 强校验。 +- 处理超时、取消、重试、并发控制。 +- 输出统一事件流:`start/chunk/result/error`。 + +不做什么: +- 不做权限决策(由 `policy` 负责)。 +- 不做主闭环编排(由 `agent` 负责)。 + +## 3. 对外接口 +- `Tool`:单工具统一执行契约。 +- `ToolMetadataProvider`:暴露工具副作用与幂等元信息。 +- `Registry`:工具注册、查询、枚举。 +- `Validator`:参数与 schema 校验。 +- `Executor`:工具执行调度与事件流封装。 +- 统一事件元字段复用 `core.EventMeta`,支持 trace 贯通。 + +## 4. 三层体系 +- 原子层:ReadFile/EditFile/WriteFile/Glob/Grep/Bash。 +- 组合层:TestRunner/GitWorkflow/TaskOutputReader。 +- 协作层:AgentTool/MCPTool/SkillTool/TeamTool。 +- 该分层用于架构分类与文档沟通,不作为 `Tool` 运行时必填字段。 + +## 5. 测试策略 +- Contract Test:schema 与事件流一致性。 +- 执行测试:超时/取消/重试语义。 +- 并发测试:配额限制与事件顺序。 diff --git a/docs/bytemind-architecture/tools/interface.go b/docs/bytemind-architecture/tools/interface.go new file mode 100644 index 00000000..3e90b275 --- /dev/null +++ b/docs/bytemind-architecture/tools/interface.go @@ -0,0 +1,109 @@ +//go:build ignore + +package tools + +import ( + "context" + "encoding/json" + "time" + + "bytemind/internal/core" +) + +type Tool interface { + Name() string + Description() string + Schema() json.RawMessage + Execute(ctx context.Context, args json.RawMessage, tctx ToolUseContext) (<-chan ToolEvent, error) +} + +type SideEffectLevel string + +const ( + SideEffectNone SideEffectLevel = "none" + SideEffectRead SideEffectLevel = "read" + SideEffectWrite SideEffectLevel = "write" + SideEffectExec SideEffectLevel = "exec" +) + +type IdempotencyLevel string + +const ( + IdempotencyStrong IdempotencyLevel = "strong" + IdempotencyWeak IdempotencyLevel = "weak" + IdempotencyUnknown IdempotencyLevel = "unknown" +) + +type ToolMetadata struct { + SideEffectLevel SideEffectLevel + IdempotencyLevel IdempotencyLevel + DefaultTimeout time.Duration + MaxRetries int +} + +type ToolMetadataProvider interface { + Metadata() ToolMetadata +} + +type ToolUseContext struct { + SessionID core.SessionID + TaskID core.TaskID + TraceID core.TraceID + Workspace string + Invoker string + Attempt int + Deadline time.Time + Metadata map[string]string +} + +type ToolEventType string + +const ( + ToolEventStart ToolEventType = "start" + ToolEventChunk ToolEventType = "chunk" + ToolEventResult ToolEventType = "result" + ToolEventError ToolEventType = "error" +) + +type ToolEvent struct { + Type ToolEventType + ToolName string + CallID string + Meta core.EventMeta + Offset int64 + Payload json.RawMessage + ErrorCode string +} + +type ErrorCode string + +const ( + ErrCodeInvalidArgument ErrorCode = "invalid_argument" + ErrCodeSchemaViolation ErrorCode = "schema_violation" + ErrCodeTimeout ErrorCode = "timeout" + ErrCodeCanceled ErrorCode = "canceled" + ErrCodeExecutionFailed ErrorCode = "execution_failed" + ErrCodeUnavailable ErrorCode = "unavailable" +) + +type ToolDescriptor struct { + Name string + Description string + Schema json.RawMessage + Metadata ToolMetadata +} + +type Registry interface { + Register(ctx context.Context, tool Tool) error + Unregister(ctx context.Context, name string) error + Get(ctx context.Context, name string) (Tool, bool) + List(ctx context.Context) ([]ToolDescriptor, error) +} + +type Validator interface { + Validate(ctx context.Context, schema json.RawMessage, args json.RawMessage) error +} + +type Executor interface { + Run(ctx context.Context, tool Tool, args json.RawMessage, tctx ToolUseContext) (<-chan ToolEvent, error) +}