diff --git a/Docs/DevOS-Platform-v2/01_ARCHITECTURE.md — DevOS Platform v2 总体架构.md b/Docs/DevOS-Platform-v2/01_ARCHITECTURE.md — DevOS Platform v2 总体架构.md new file mode 100644 index 0000000..10d7c5f --- /dev/null +++ b/Docs/DevOS-Platform-v2/01_ARCHITECTURE.md — DevOS Platform v2 总体架构.md @@ -0,0 +1,1876 @@ +# DevOS Platform v2 +## 01 — Overall Architecture Specification + +**Document Version:** 2.0 +**Status:** Architecture Specification +**Target:** DevOS Platform +**Implementation Target:** Zcode / AI Coding Agent + +--- + +# 1. 文档目的 + +DevOS v2 不再被定义为单一的后台管理系统,而定义为: + +> 一个可以承载多个 Application、Plugin、MCP、Skill、Agent 和 Workflow 的可扩展应用运行平台。 + +DevOS 的目标不是让每一个项目都重新开发: + +- 登录 +- 用户 +- 权限 +- 菜单 +- Dashboard +- 文件 +- 通知 +- Task +- Job +- Event +- API +- Audit +- Agent +- MCP +- Plugin +- Settings + +而是将这些能力沉淀为 DevOS Platform 的公共基础能力。 + +未来新产品原则: + +```text +New Product + ↓ +Reuse DevOS Core + ↓ +Reuse DevOS Runtime + ↓ +Reuse DevOS UI + ↓ +Implement Business Domain +``` + +--- + +# 2. 核心目标 + +DevOS v2 必须解决以下问题。 + +## 2.1 多项目复用 + +多个产品共享: + +```text +Authentication +Authorization +Users +Organizations +Roles +Permissions +Resources +Actions +Events +Tasks +Jobs +Files +Storage +Notifications +Audit +Settings +Search +API +UI +Agent Runtime +Plugin Runtime +MCP Runtime +Skill Runtime +``` + +--- + +## 2.2 应用可插拔 + +一个业务应用应该能够被安装到 DevOS,而不是修改 DevOS Core。 + +例如: + +```text +DevOS +├── SEO +├── DevOps +├── Monitoring +├── CRM +└── Project Management +``` + +这些都应该是 App,而不是 Core。 + +--- + +## 2.3 能力可扩展 + +业务能力应该能够通过 Plugin 扩展。 + +例如: + +```text +SEO App +├── Keyword Plugin +├── Content Plugin +├── Backlink Plugin +├── Search Console Plugin +└── Analytics Plugin +``` + +--- + +## 2.4 AI 原生 + +DevOS v2 必须从架构层面支持: + +```text +Agent +Skill +MCP +Tool +Action +Context +Workflow +Memory +Event +``` + +Agent 不应该拥有一套独立的业务 API。 + +Agent 应该调用 DevOS 的统一 Action 系统。 + +--- + +# 3. 总体架构 + +DevOS v2 采用五层结构: + +```text +┌─────────────────────────────────────────────┐ +│ Applications │ +│ │ +│ SEO / DevOps / CRM / Monitoring / ... │ +├─────────────────────────────────────────────┤ +│ Extensions │ +│ │ +│ Plugin / MCP / Skill / Widget / Integration│ +├─────────────────────────────────────────────┤ +│ Runtime │ +│ │ +│ App Runtime / Agent / Workflow / Scheduler │ +├─────────────────────────────────────────────┤ +│ Core │ +│ │ +│ Auth / User / Permission / Resource / │ +│ Action / Event / Task / File / Audit │ +├─────────────────────────────────────────────┤ +│ Infrastructure │ +│ │ +│ PostgreSQL / Redis / Object Storage / Queue│ +└─────────────────────────────────────────────┘ +``` + +--- + +# 4. Architecture Principles + +## 4.1 Core First + +Core 只提供平台级能力。 + +Core 不允许包含具体业务领域。 + +允许: + +```text +User +Role +Permission +Resource +Action +Task +Event +File +Audit +``` + +不允许: + +```text +SEOKeyword +Backlink +CRMLead +Invoice +Campaign +``` + +这些属于 Application。 + +--- + +# 5. Core + +DevOS Core 是所有 Application 共用的基础。 + +建议模块: + +```text +core/ +├── identity/ +├── auth/ +├── organization/ +├── user/ +├── role/ +├── permission/ +├── resource/ +├── action/ +├── event/ +├── task/ +├── job/ +├── file/ +├── storage/ +├── notification/ +├── audit/ +├── settings/ +├── search/ +└── api/ +``` + +--- + +# 6. Identity + +Identity 管理: + +```text +User +Organization +Membership +Session +Account +Identity Provider +``` + +支持: + +```text +Email +Password +OAuth +OIDC +API Key +Service Account +Agent Identity +``` + +--- + +# 7. Authorization + +DevOS v2 不使用单纯的: + +```text +user -> role -> permission +``` + +而采用: + +```text +Subject + ↓ +Permission + ↓ +Resource + ↓ +Action + ↓ +Scope +``` + +统一模型: + +```text +Permission = + subject + + resource + + action + + scope +``` + +例如: + +```text +seo.website.read +seo.website.update +seo.website.scan +seo.website.publish +``` + +--- + +# 8. Resource Model + +Resource 是 DevOS 的核心抽象。 + +所有可管理对象都应该可以注册为 Resource。 + +例如: + +```text +User +Website +Project +Keyword +Content +Backlink +Server +Deployment +Report +``` + +Resource 定义: + +```ts +interface ResourceDefinition { + name: string + label: string + + schema: unknown + + actions: ActionDefinition[] + + permissions: PermissionDefinition[] + + ui?: ResourceUI + + events?: EventDefinition[] +} +``` + +--- + +# 9. Action Model + +Resource 不只是 CRUD。 + +每个 Resource 可以拥有多个 Action。 + +例如: + +```text +Website + +read +create +update +delete +scan +analyze +verify +deploy +backup +``` + +Action: + +```ts +interface ActionDefinition { + name: string + resource: string + + inputSchema?: unknown + outputSchema?: unknown + + permission?: string + + execute(context, input): Promise +} +``` + +--- + +# 10. Human 与 Agent 统一执行模型 + +这是 DevOS v2 最重要的设计之一。 + +UI: + +```text +User + ↓ +UI + ↓ +Action + ↓ +Resource +``` + +Agent: + +```text +Agent + ↓ +Skill + ↓ +Action + ↓ +Resource +``` + +MCP: + +```text +MCP + ↓ +Action + ↓ +Resource +``` + +API: + +```text +API + ↓ +Action + ↓ +Resource +``` + +最终全部进入: + +```text +Action Runtime +``` + +因此业务逻辑不能写在: + +```text +React Component +REST Controller +Agent +MCP Server +``` + +而应该写在: + +```text +Action +``` + +--- + +# 11. Event Model + +所有重要状态变化都应该产生 Event。 + +例如: + +```text +website.created +website.updated +website.scan.started +website.scan.completed + +content.created +content.published + +backlink.created +backlink.lost +``` + +事件模型: + +```ts +interface DevEvent { + id: string + type: string + + actor: Actor + resource?: ResourceRef + + payload: unknown + + createdAt: Date +} +``` + +Event 可以触发: + +```text +Notification +Task +Workflow +Agent +Plugin +Webhook +Audit +``` + +--- + +# 12. Task / Job + +DevOS 区分: + +```text +Task +Job +Workflow +``` + +### Task + +用户或 Agent 需要完成的工作。 + +```text +Analyze Website +Generate Article +Review Backlinks +``` + +### Job + +后台执行单元。 + +```text +crawlWebsite() +generateEmbedding() +syncSearchConsole() +``` + +### Workflow + +多个 Action / Job 的组合。 + +```text +Scan Website + ↓ +Analyze SEO + ↓ +Generate Report + ↓ +Create Tasks + ↓ +Notify User +``` + +--- + +# 13. Plugin Architecture + +Plugin 是 DevOS 扩展能力的基本单位。 + +Plugin 可以提供: + +```text +Backend +Frontend +Routes +Pages +Navigation +Resources +Actions +Events +Workers +Tasks +Settings +Permissions +Widgets +MCP +Skills +``` + +Plugin Manifest: + +```ts +interface PluginManifest { + id: string + name: string + version: string + + permissions?: string[] + + resources?: string[] + actions?: string[] + + routes?: RouteDefinition[] + navigation?: NavigationDefinition[] + + settings?: SettingDefinition[] + + capabilities?: CapabilityDefinition[] +} +``` + +--- + +# 14. Plugin 生命周期 + +Plugin 必须支持: + +```text +discover +install +validate +enable +disable +configure +update +uninstall +``` + +生命周期: + +```text +Plugin Package + ↓ +Discover + ↓ +Install + ↓ +Migration + ↓ +Register + ↓ +Enable + ↓ +Running +``` + +--- + +# 15. MCP Architecture + +MCP 被视为外部能力连接层。 + +MCP 不应该直接修改业务数据库。 + +推荐: + +```text +MCP Tool + ↓ +DevOS Action + ↓ +Resource +``` + +而不是: + +```text +MCP + ↓ +Database +``` + +这样可以统一: + +```text +Permission +Validation +Audit +Event +Rate Limit +Transaction +``` + +--- + +# 16. Skill Architecture + +Skill 是 Agent 能力编排层。 + +例如: + +```text +seo.website.audit +seo.keyword.research +seo.content.generate +seo.backlink.analyze +``` + +Skill 可以调用: + +```text +Action +MCP +Plugin +Workflow +Other Skill +``` + +结构: + +```text +Skill + ├── Context + ├── Instructions + ├── Inputs + ├── Actions + ├── MCP + ├── Outputs + └── Validation +``` + +--- + +# 17. Agent Architecture + +Agent 不应该直接访问数据库。 + +Agent: + +```text +Agent + ↓ +Context + ↓ +Skill + ↓ +Action / MCP + ↓ +Resource +``` + +Agent Runtime 负责: + +```text +Planning +Tool Selection +Skill Selection +Execution +Observation +Retry +Approval +Memory +Context +``` + +--- + +# 18. Application Architecture + +Application 是业务产品。 + +例如: + +```text +apps/ +├── seo/ +├── devops/ +├── monitoring/ +└── crm/ +``` + +每个 App 应该只负责: + +```text +Business Domain +Business UI +Business Resources +Business Actions +Business Workflows +``` + +而不应该重新实现: + +```text +Auth +User +Permission +Task +Notification +File +Audit +Agent Runtime +Plugin Runtime +``` + +--- + +# 19. App Manifest + +每个 App 应该拥有: + +```ts +interface AppManifest { + id: string + name: string + version: string + + description?: string + + dependencies?: string[] + + permissions?: string[] + + resources?: string[] + actions?: string[] + + navigation?: NavigationDefinition[] + + dashboard?: DashboardDefinition +} +``` + +--- + +# 20. Application Shell + +DevOS 提供统一 Application Shell: + +```text +┌───────────────────────────────────────────┐ +│ DevOS Header │ +├────────────┬──────────────────────────────┤ +│ │ │ +│ Navigation │ Application │ +│ │ │ +│ │ │ +│ │ │ +├────────────┴──────────────────────────────┤ +│ Status / Notifications / Tasks │ +└───────────────────────────────────────────┘ +``` + +App 不需要重新开发: + +```text +Header +Sidebar +User Menu +Notification +Command Palette +Theme +Permission Guard +``` + +--- + +# 21. Navigation + +Navigation 应由 App / Plugin 注册。 + +例如: + +```ts +registerNavigation({ + id: 'seo', + label: 'SEO', + icon: 'Search', + children: [ + { + id: 'websites', + label: 'Websites', + path: '/seo/websites', + }, + { + id: 'keywords', + label: 'Keywords', + path: '/seo/keywords', + }, + ], +}) +``` + +DevOS Shell 自动合并。 + +最终: + +```text +DevOS +├── Dashboard +├── Projects +├── SEO +│ ├── Websites +│ ├── Keywords +│ ├── Content +│ └── Backlinks +├── DevOps +└── Settings +``` + +--- + +# 22. UI Architecture + +建立: + +```text +@devos/ui +``` + +提供统一组件: + +```text +DevLayout +DevPage +DevTable +DevForm +DevDrawer +DevModal +DevDetail +DevResource +DevAction +DevTask +DevStatus +DevTimeline +DevDashboard +DevWidget +DevAgentChat +DevCommandPalette +``` + +业务 App 不应该重复实现基础管理 UI。 + +--- + +# 23. SDK + +DevOS 必须提供官方 SDK。 + +建议: + +```text +@devos/sdk +@devos/plugin-sdk +@devos/app-sdk +@devos/mcp-sdk +@devos/skill-sdk +@devos/agent-sdk +``` + +SDK 用于: + +```text +注册 Resource +注册 Action +注册 Event +注册 Page +注册 Navigation +注册 Plugin +注册 MCP +注册 Skill +注册 Agent +``` + +--- + +# 24. CLI + +DevOS CLI: + +```bash +devos create +devos dev +devos build +devos validate +devos install +devos plugin +devos app +devos mcp +devos skill +devos migrate +devos doctor +``` + +创建项目: + +```bash +devos create app my-app +``` + +创建 Plugin: + +```bash +devos create plugin my-plugin +``` + +创建 MCP: + +```bash +devos create mcp my-mcp +``` + +创建 Skill: + +```bash +devos create skill my-skill +``` + +创建独立产品: + +```bash +devos create standalone my-product +``` + +--- + +# 25. Standalone Fork + +DevOS 必须支持 Fork 模式。 + +提供: + +```text +DevOS Base + ↓ +Standalone Template + ↓ +Independent Product +``` + +Standalone Product 默认拥有: + +```text +Auth +User +Organization +Role +Permission +Resource +Action +Event +Task +Job +File +Notification +Audit +Plugin Runtime +MCP Runtime +Skill Runtime +Agent Runtime +UI +CLI +``` + +之后可以自由删除不需要的模块。 + +--- + +# 26. Monorepo + +建议使用 Monorepo。 + +基础结构: + +```text +devos/ +│ +├── apps/ +│ ├── shell/ +│ ├── api/ +│ └── worker/ +│ +├── packages/ +│ ├── core/ +│ ├── runtime/ +│ ├── sdk/ +│ ├── ui/ +│ ├── plugin-sdk/ +│ ├── app-sdk/ +│ ├── mcp-sdk/ +│ ├── skill-sdk/ +│ └── agent-sdk/ +│ +├── plugins/ +│ +├── applications/ +│ +├── templates/ +│ +├── cli/ +│ +└── docs/ +``` + +--- + +# 27. Dependency Rules + +依赖方向必须严格控制: + +```text +Application + ↓ +Runtime + ↓ +Core + ↓ +Infrastructure +``` + +禁止: + +```text +Core → Application +Core → Plugin +Core → SEO +``` + +禁止业务反向污染 Core。 + +--- + +# 28. Core 与 Runtime 的边界 + +Core: + +```text +稳定 +基础 +通用 +长期存在 +``` + +Runtime: + +```text +执行 +扩展 +编排 +动态加载 +``` + +Application: + +```text +业务 +产品 +用户价值 +``` + +Plugin: + +```text +可选能力 +第三方集成 +业务扩展 +``` + +--- + +# 29. 数据库原则 + +Core 数据库表使用统一命名空间。 + +例如: + +```text +devos_users +devos_organizations +devos_roles +devos_permissions +devos_sessions +devos_events +devos_tasks +devos_jobs +devos_audit_logs +``` + +App 数据表独立命名。 + +例如 SEO: + +```text +seo_websites +seo_keywords +seo_content +seo_backlinks +seo_campaigns +``` + +Plugin: + +```text +plugin_xxx_* +``` + +禁止 Plugin 随意修改 Core 表。 + +--- + +# 30. API 原则 + +API 分为: + +```text +Core API +Runtime API +App API +Plugin API +``` + +但是最终业务执行应该尽量统一到: + +```text +Action API +``` + +例如: + +```http +POST /api/actions/seo.website.scan +``` + +而不是为同一个业务逻辑维护: + +```text +REST +GraphQL +Agent API +MCP API +Internal API +``` + +五套不同实现。 + +--- + +# 31. Audit + +所有敏感 Action 自动记录: + +```text +actor +action +resource +input +result +ip +userAgent +timestamp +requestId +``` + +例如: + +```text +user:123 +seo.website.publish +website:456 +success +``` + +Agent 执行同样记录。 + +例如: + +```text +agent:seo-agent +seo.website.scan +website:456 +success +``` + +这样 Human 与 AI 的行为可以统一审计。 + +--- + +# 32. Observability + +DevOS 必须内置: + +```text +Logging +Metrics +Tracing +Audit +Health Check +Error Tracking +``` + +所有 Runtime 执行应该拥有: + +```text +requestId +traceId +executionId +``` + +例如: + +```text +Agent Execution + │ + ├── Skill Execution + │ │ + │ ├── Action + │ ├── MCP + │ └── Action + │ + └── Workflow +``` + +整个链路必须可以追踪。 + +--- + +# 33. Security + +所有 Extension 必须拥有明确权限。 + +Plugin: + +```text +declared permissions +``` + +MCP: + +```text +declared tools +declared permissions +``` + +Skill: + +```text +declared actions +``` + +Agent: + +```text +declared capabilities +``` + +默认: + +```text +DENY +``` + +而不是: + +```text +ALLOW +``` + +--- + +# 34. Extension Isolation + +Plugin 不允许默认获得: + +```text +Database Full Access +Filesystem Full Access +Shell Access +Network Full Access +``` + +必须通过 Capability: + +```text +database.read +database.write + +filesystem.read +filesystem.write + +network.http + +process.execute +``` + +并经过权限检查。 + +--- + +# 35. Configuration + +配置分为: + +```text +Platform Config +App Config +Plugin Config +User Config +Organization Config +Environment Config +``` + +统一 Configuration API。 + +例如: + +```ts +config.get('seo.crawler.maxConcurrency') +``` + +而不是每个项目自己实现 Settings。 + +--- + +# 36. Storage + +DevOS 提供统一 Storage API: + +```ts +storage.put() +storage.get() +storage.delete() +storage.exists() +storage.url() +``` + +底层可以使用: + +```text +Local +S3 +Cloudflare R2 +MinIO +``` + +Application 不应该直接依赖具体 Storage Provider。 + +--- + +# 37. Queue + +统一 Queue: + +```text +@devos/queue +``` + +支持: + +```text +Job +Retry +Delay +Priority +Concurrency +Dead Letter +Cancellation +Progress +``` + +业务只提交 Job: + +```ts +queue.dispatch('seo.scan', payload) +``` + +不直接依赖 Redis 实现。 + +--- + +# 38. Scheduler + +统一 Scheduler: + +```text +schedule.every() +schedule.cron() +schedule.once() +``` + +例如: + +```text +Every 6 hours + ↓ +Search Console Sync + +Every day + ↓ +SEO Audit + +Every week + ↓ +Report Generation +``` + +--- + +# 39. Search + +建立统一 Search abstraction: + +```text +search.index() +search.query() +search.remove() +``` + +未来可以使用: + +```text +PostgreSQL +Meilisearch +OpenSearch +Elasticsearch +``` + +Application 不直接绑定具体搜索引擎。 + +--- + +# 40. Notification + +统一 Notification: + +```text +In-App +Email +Webhook +Push +Slack +Discord +``` + +例如: + +```ts +notification.send({ + userId, + type: 'task.completed', +}) +``` + +--- + +# 41. DevOS Application Lifecycle + +App: + +```text +discover +install +migrate +register +enable +disable +update +uninstall +``` + +启动: + +```text +Load Core + ↓ +Load Runtime + ↓ +Discover Apps + ↓ +Validate Manifest + ↓ +Load Dependencies + ↓ +Register Resources + ↓ +Register Actions + ↓ +Register Events + ↓ +Register Routes + ↓ +Register Navigation + ↓ +Application Ready +``` + +--- + +# 42. DevOS 的最终产品模型 + +DevOS 中存在四种主要扩展单位: + +```text +App +Plugin +MCP +Skill +``` + +它们关系: + +```text +App + ├── Plugin + │ ├── Resource + │ ├── Action + │ └── UI + │ + ├── MCP + │ + ├── Skill + │ + └── Agent +``` + +--- + +# 43. SEO App 示例 + +未来 AI SEO 应该表现为: + +```text +applications/ +└── seo/ + ├── manifest.ts + │ + ├── resources/ + │ ├── website.ts + │ ├── keyword.ts + │ ├── content.ts + │ └── backlink.ts + │ + ├── actions/ + │ ├── scan.ts + │ ├── analyze.ts + │ ├── generate.ts + │ └── publish.ts + │ + ├── pages/ + │ + ├── workflows/ + │ + └── dashboard/ +``` + +SEO 本身不负责: + +```text +Auth +User +Permission +Task Engine +Queue +Notification +Agent Runtime +MCP Runtime +Plugin Runtime +``` + +--- + +# 44. 新项目开发原则 + +未来创建新项目时,必须首先回答: + +### Q1 + +这是: + +```text +Plugin +App +Standalone +``` + +哪一种? + +--- + +### Q2 + +这个能力是否已经存在于 DevOS Core? + +如果存在: + +```text +REUSE +``` + +禁止重复实现。 + +--- + +### Q3 + +这个能力是否属于 Runtime? + +如果属于: + +```text +EXTEND RUNTIME +``` + +--- + +### Q4 + +是否属于业务领域? + +如果是: + +```text +APP MODULE +``` + +--- + +### Q5 + +是否可以独立复用? + +如果可以: + +```text +PLUGIN +``` + +--- + +# 45. Golden Rule + +DevOS v2 必须遵守: + +> **Build Once, Reuse Everywhere.** + +以及: + +> **Business Logic Lives in Actions.** + +以及: + +> **AI Uses the Same Actions as Humans.** + +以及: + +> **Core Must Never Depend on Business Applications.** + +以及: + +> **Everything Extensible Must Have a Manifest.** + +--- + +# 46. 成功标准 + +DevOS v2 完成后,创建一个新的普通 SaaS 应用: + +不应该重新实现: + +```text +Login +Register +User +Organization +Role +Permission +Navigation +Layout +Notification +File +Storage +Task +Job +Audit +Search +Settings +API +Agent +MCP +Plugin +``` + +开发者只需要: + +```text +1. Define App Manifest +2. Define Resources +3. Define Actions +4. Define Pages +5. Define Workflows +6. Add Plugins +``` + +--- + +# 47. 最终目标 + +DevOS 的最终形态: + +```text + DEVOS PLATFORM + │ + ┌───────────────────┼───────────────────┐ + │ │ │ + Core Runtime UI + │ │ │ + │ ┌────────┼────────┐ │ + │ │ │ │ │ + │ Agent Plugin MCP │ + │ │ │ │ │ + └──────────┴────────┴────────┴──────────┘ + │ + Application Layer + │ + ┌─────────────┼─────────────┐ + │ │ │ + SEO DevOps CRM + │ │ │ + Plugins Plugins Plugins +``` + +DevOS 本身不是最终业务产品。 + +**DevOS 是生产这些业务产品的平台。** + +--- + +# 48. 实施原则 + +Zcode 在实施 DevOS v2 时必须遵循: + +1. 不破坏现有可工作的 DevOS 功能。 +2. 优先重构边界,而不是增加重复功能。 +3. Core 与 Application 必须严格分离。 +4. 新功能优先考虑是否应该成为 Plugin。 +5. 所有可执行业务操作优先进入 Action Runtime。 +6. Agent / MCP / UI / API 尽量共享 Action。 +7. 不允许业务代码反向进入 Core。 +8. 不允许每个 App 自建 Auth / Permission / Task 等基础设施。 +9. 所有 Extension 必须 Manifest 化。 +10. 所有重大执行必须可 Audit。 +11. 所有后台 Job 必须进入统一 Job Runtime。 +12. 所有异步事件必须进入统一 Event System。 +13. 新架构必须支持未来 Standalone Fork。 +14. API、SDK、CLI 必须围绕同一 Runtime 模型设计。 +15. 不为了架构漂亮而进行没有实际价值的微服务拆分。 + +--- + +# 49. 下一阶段 + +本文件只定义总体架构。 + +后续文档应继续详细定义: + +```text +02_CORE_ARCHITECTURE.md +03_RESOURCE_ACTION_MODEL.md +04_EVENT_TASK_JOB.md +05_PLUGIN_SYSTEM.md +06_APP_RUNTIME.md +07_MCP_RUNTIME.md +08_SKILL_RUNTIME.md +09_AGENT_RUNTIME.md +10_PERMISSION_SECURITY.md +11_UI_DESIGN_SYSTEM.md +12_SDK.md +13_CLI.md +14_DATABASE.md +15_API.md +16_PROJECT_TEMPLATES.md +17_STANDALONE_FORK.md +18_MIGRATION.md +19_IMPLEMENTATION_PLAN.md +20_ACCEPTANCE_TESTS.md +``` + +这些文档完成后,再进入 Zcode 实际代码改造阶段。 + +**禁止在总体架构未确定之前大规模修改现有业务代码。** \ No newline at end of file diff --git a/Docs/DevOS-Platform-v2/02_CORE_ARCHITECTURE.md — DevOS Core 核心架构.md b/Docs/DevOS-Platform-v2/02_CORE_ARCHITECTURE.md — DevOS Core 核心架构.md new file mode 100644 index 0000000..775a9f8 --- /dev/null +++ b/Docs/DevOS-Platform-v2/02_CORE_ARCHITECTURE.md — DevOS Core 核心架构.md @@ -0,0 +1,2018 @@ +# DevOS Platform v2 +## 02 — Core Architecture Specification + +**Document Version:** 2.0 +**Status:** Architecture Specification +**Parent Document:** `01_ARCHITECTURE.md` +**Target:** DevOS Platform v2 +**Implementation Target:** Zcode / AI Coding Agent + +--- + +# 1. Core 定义 + +DevOS Core 是整个 DevOS Platform 的稳定基础层。 + +Core 的职责是提供所有 Application、Plugin、MCP、Skill、Agent 都可能依赖的通用能力。 + +Core 不属于任何业务领域。 + +Core 的设计目标: + +```text +Stable +Reusable +Predictable +Secure +Minimal +Business-Agnostic +``` + +--- + +# 2. Core 的核心原则 + +必须遵循: + +> Core 提供能力,不提供业务。 + +例如: + +允许: + +```text +User +Organization +Role +Permission +Resource +Action +Event +Task +Job +File +Storage +Notification +Audit +Settings +``` + +禁止: + +```text +SEOKeyword +Backlink +CRMLead +Invoice +ProductOrder +Campaign +Article +WebsiteSEOScore +``` + +这些属于 Application / Plugin。 + +--- + +# 3. Core 模块总览 + +DevOS Core 第一阶段包含: + +```text +core/ +├── identity/ +├── organization/ +├── auth/ +├── authorization/ +├── resource/ +├── action/ +├── event/ +├── task/ +├── job/ +├── file/ +├── storage/ +├── notification/ +├── audit/ +├── settings/ +├── search/ +├── api/ +├── error/ +├── validation/ +├── logging/ +├── health/ +└── config/ +``` + +--- + +# 4. Core 不应该过度拆分 + +不要为了“模块化”而产生数十个没有实际边界的 package。 + +以下内容可以属于 Core: + +```text +Auth +User +Organization +Permission +Resource +Action +Event +Task +Job +File +Storage +Notification +Audit +Settings +``` + +但不应该出现: + +```text +UserNameService +UserAvatarService +UserPreferenceService +UserEmailService +``` + +除非存在明确的独立生命周期和依赖边界。 + +--- + +# 5. Core 分层 + +Core 内部继续分为: + +```text +Foundation +Domain +Application +Infrastructure +``` + +结构: + +```text +┌─────────────────────────────┐ +│ Application │ +│ API / Command / Query │ +├─────────────────────────────┤ +│ Domain │ +│ Identity / Auth / Resource │ +├─────────────────────────────┤ +│ Foundation │ +│ Types / Errors / Events │ +├─────────────────────────────┤ +│ Infrastructure │ +│ DB / Redis / Storage / Queue│ +└─────────────────────────────┘ +``` + +--- + +# 6. Foundation + +Foundation 是最底层。 + +不得依赖: + +```text +Application +Plugin +MCP +Agent +具体业务 +``` + +包含: + +```text +types +errors +result +ids +time +events +validation +contracts +``` + +例如: + +```ts +type ID = string + +interface Entity { + id: ID + createdAt: Date + updatedAt: Date +} +``` + +--- + +# 7. Domain + +Domain 定义 Core 的核心对象。 + +例如: + +```text +User +Organization +Role +Permission +Resource +Action +Task +Job +Event +File +Notification +AuditLog +``` + +Domain 不直接操作: + +```text +PostgreSQL +Redis +S3 +HTTP +Filesystem +``` + +通过 Repository / Port 抽象访问。 + +--- + +# 8. Infrastructure + +Infrastructure 实现具体技术。 + +例如: + +```text +PostgresUserRepository +RedisEventBus +S3Storage +BullMQJobQueue +``` + +Application / Domain 不应该依赖这些具体实现。 + +推荐: + +```text +Domain + ↓ +Interface + ↓ +Infrastructure +``` + +而不是: + +```text +Domain + ↓ +Prisma +``` + +--- + +# 9. Identity + +Identity 是用户身份基础设施。 + +包含: + +```text +User +Account +Identity +Session +ServiceAccount +AgentIdentity +``` + +--- + +# 10. User + +User 是 DevOS 全局用户。 + +用户模型最少包含: + +```ts +interface User { + id: string + email?: string + username?: string + + displayName?: string + avatarUrl?: string + + status: UserStatus + + createdAt: Date + updatedAt: Date +} +``` + +禁止 App 自己创建第二套 User。 + +--- + +# 11. Organization + +DevOS 应默认支持多组织。 + +结构: + +```text +User + │ + ├── Organization A + │ + └── Organization B +``` + +Membership: + +```ts +interface Membership { + userId: string + organizationId: string + + roles: string[] + + status: MembershipStatus +} +``` + +这使未来可以支持: + +```text +Personal Workspace +Team +Company +Agency +Client Workspace +``` + +--- + +# 12. Auth + +Auth 负责: + +```text +Authentication +Session +Login +Logout +Credential Verification +OAuth +OIDC +API Key +``` + +Auth 不负责: + +```text +业务 Permission +SEO Permission +Plugin Permission +``` + +这些由 Authorization 负责。 + +--- + +# 13. Authentication Provider + +Auth 应采用 Provider 模型: + +```text +AuthProvider +├── Password +├── OAuth +├── OIDC +├── SSO +└── APIKey +``` + +统一: + +```ts +interface AuthProvider { + id: string + + authenticate(input: unknown): Promise + + revoke(sessionId: string): Promise +} +``` + +这样未来增加: + +```text +Google +GitHub +Microsoft +Apple +OIDC +SAML +``` + +不需要修改 Core Auth 主体。 + +--- + +# 14. Authorization + +Authorization 负责: + +```text +Role +Permission +Policy +Scope +Access Check +``` + +核心接口: + +```ts +interface AuthorizationService { + check(input: AuthorizationRequest): Promise + + require(input: AuthorizationRequest): Promise +} +``` + +--- + +# 15. Role + +Role 是 Permission 的集合。 + +例如: + +```text +Admin +Manager +Editor +Viewer +Agent +``` + +Role 不应该直接绑定具体页面。 + +错误: + +```text +Admin -> /settings +``` + +正确: + +```text +Admin + ↓ +permission + ↓ +resource.action +``` + +--- + +# 16. Permission + +Permission 格式: + +```text +. +``` + +例如: + +```text +user.read +user.update + +project.read +project.create +project.update +project.delete +``` + +App 可以扩展: + +```text +seo.website.read +seo.website.scan +seo.website.publish +``` + +--- + +# 17. Scope + +Permission 还必须支持 Scope。 + +例如: + +```text +global +organization +project +resource +owner +``` + +示例: + +```text +project.update +scope = organization +``` + +表示用户只能修改当前 Organization 下的 Project。 + +--- + +# 18. Resource + +Resource 是 Core 最重要的抽象之一。 + +Core 提供: + +```text +Resource Registry +Resource Metadata +Resource Reference +Resource Permissions +Resource Actions +``` + +但具体业务 Resource 由 App 注册。 + +Core 自身只注册: + +```text +User +Organization +Role +Permission +Task +Job +File +``` + +--- + +# 19. Resource Reference + +统一 Resource Reference: + +```ts +interface ResourceRef { + type: string + id: string +} +``` + +例如: + +```json +{ + "type": "seo.website", + "id": "website_123" +} +``` + +任何系统都可以引用: + +```text +Task +Event +Audit +Notification +Action +Agent +Workflow +``` + +--- + +# 20. Action + +Action 是 Core 与 Runtime 的连接点。 + +Core 提供: + +```text +Action Registry +Action Validation +Action Authorization +Action Execution Context +Action Audit +Action Event +``` + +Action 不应该绑定 HTTP。 + +错误: + +```ts +scanWebsite(req, res) +``` + +正确: + +```ts +scanWebsite.execute(context, input) +``` + +HTTP、MCP、Agent、CLI 都调用相同 Action。 + +--- + +# 21. Action Context + +统一 Action Context: + +```ts +interface ActionContext { + requestId: string + executionId: string + + actor: ActorContext + + organizationId?: string + + permissions: string[] + + metadata?: Record +} +``` + +Actor: + +```ts +type ActorContext = + | UserActor + | AgentActor + | ServiceActor + | SystemActor +``` + +--- + +# 22. Event + +Core 提供 Event Bus。 + +接口: + +```ts +interface EventBus { + publish(event: DevEvent): Promise + + subscribe( + eventType: string, + handler: EventHandler + ): Unsubscribe +} +``` + +Event 可以: + +```text +persist +publish +subscribe +retry +replay +``` + +--- + +# 23. Event 与 Action + +Action 成功执行后可以产生 Event。 + +例如: + +```text +seo.website.scan + ↓ +Action + ↓ +success + ↓ +seo.website.scan.completed +``` + +Core 不关心: + +```text +SEO +``` + +它只负责: + +```text +Action → Event +``` + +--- + +# 24. Task + +Task 是用户可见的工作对象。 + +例如: + +```text +Review Article +Verify Website +Fix Broken Links +``` + +Task 模型: + +```ts +interface Task { + id: string + + title: string + description?: string + + status: TaskStatus + + assigneeId?: string + + organizationId?: string + + resource?: ResourceRef + + createdBy: ActorRef + + createdAt: Date + updatedAt: Date +} +``` + +--- + +# 25. Job + +Job 是后台执行单元。 + +例如: + +```text +crawl +sync +embedding +report generation +``` + +Job 与 Task 不等价。 + +```text +Task = Work Item +Job = Execution Unit +``` + +--- + +# 26. Job Queue + +Core 提供 Queue Contract: + +```ts +interface JobQueue { + dispatch( + name: string, + payload: T, + options?: JobOptions + ): Promise +} +``` + +Infrastructure 决定实际实现: + +```text +Redis +BullMQ +RabbitMQ +SQS +Database Queue +``` + +Application 不直接依赖 Queue Provider。 + +--- + +# 27. File + +File 是平台级资源。 + +统一 File API: + +```ts +interface FileService { + create(input: CreateFileInput): Promise + + get(id: string): Promise + + delete(id: string): Promise + + getUrl(id: string): Promise +} +``` + +App 不直接操作: + +```text +S3 SDK +filesystem +R2 SDK +``` + +--- + +# 28. Storage + +Storage Provider: + +```text +LocalStorage +S3Storage +R2Storage +MinIOStorage +``` + +统一接口: + +```ts +interface StorageProvider { + put(input: StoragePutInput): Promise + get(key: string): Promise + delete(key: string): Promise + exists(key: string): Promise +} +``` + +--- + +# 29. Notification + +Notification 是 Core Service。 + +支持: + +```text +in-app +email +webhook +push +``` + +但具体 Provider 属于 Extension。 + +例如: + +```text +Email Provider +Slack Provider +Discord Provider +``` + +可以实现为 Plugin。 + +--- + +# 30. Audit + +Audit 是强制能力。 + +以下操作必须支持 Audit: + +```text +Authentication +Authorization changes +Permission changes +Sensitive Action +Plugin install +Plugin enable +Plugin disable +Settings changes +API key creation +Agent execution +``` + +Audit: + +```ts +interface AuditRecord { + id: string + + actor: ActorRef + + action: string + + resource?: ResourceRef + + result: 'success' | 'failure' + + metadata?: Record + + createdAt: Date +} +``` + +--- + +# 31. Settings + +Settings 分层: + +```text +System +Organization +User +App +Plugin +``` + +Key 示例: + +```text +system.locale +organization.timezone +user.theme +seo.crawler.concurrency +plugin.github.token +``` + +权限必须作用于 Settings。 + +--- + +# 32. Config + +Config 与 Settings 必须区分。 + +Config: + +```text +Environment / Deployment +``` + +例如: + +```text +DATABASE_URL +REDIS_URL +STORAGE_ENDPOINT +``` + +Settings: + +```text +Runtime / User configurable +``` + +例如: + +```text +theme +timezone +crawler concurrency +``` + +禁止把 Secret 全部存入 Settings。 + +--- + +# 33. Secret + +Secret 必须独立处理。 + +例如: + +```text +API Keys +OAuth Client Secret +Webhook Secret +Cloud Credentials +MCP Credentials +``` + +统一: + +```ts +interface SecretStore { + get(key: string): Promise + + set(key: string, value: string): Promise + + delete(key: string): Promise +} +``` + +生产环境优先: + +```text +Vault +Cloud Secret Manager +Environment Secret +Encrypted Database +``` + +--- + +# 34. Search + +Search 只定义抽象: + +```ts +interface SearchService { + index(input: SearchDocument): Promise + + search(input: SearchQuery): Promise + + remove(index: string, id: string): Promise +} +``` + +可以替换: + +```text +PostgreSQL +Meilisearch +OpenSearch +Elasticsearch +``` + +--- + +# 35. Logging + +统一 Logger: + +```ts +logger.info() +logger.warn() +logger.error() +logger.debug() +``` + +必须自动附带: + +```text +requestId +executionId +organizationId +actorId +``` + +如果存在。 + +--- + +# 36. Health + +统一: + +```text +/health +/health/live +/health/ready +``` + +检查: + +```text +Database +Redis +Storage +Queue +External Dependencies +``` + +--- + +# 37. Error Model + +所有 Core / Runtime / App 错误必须遵循统一 Error Contract。 + +```ts +interface DevError { + code: string + + message: string + + status?: number + + details?: unknown + + cause?: unknown + + requestId?: string +} +``` + +例如: + +```text +AUTH_REQUIRED +PERMISSION_DENIED +RESOURCE_NOT_FOUND +ACTION_NOT_FOUND +ACTION_INVALID +PLUGIN_NOT_FOUND +PLUGIN_DISABLED +``` + +禁止每个 App 自定义完全不同的错误格式。 + +--- + +# 38. Validation + +统一 Schema Validation。 + +推荐: + +```text +Zod +``` + +Action: + +```ts +inputSchema +outputSchema +``` + +必须在 Runtime 中验证。 + +流程: + +```text +Input + ↓ +Schema Validation + ↓ +Authorization + ↓ +Action + ↓ +Output Validation +``` + +--- + +# 39. API Layer + +API Layer 不是 Core Business Logic。 + +它只是 Adapter。 + +例如: + +```text +REST Adapter +RPC Adapter +MCP Adapter +CLI Adapter +Agent Adapter +``` + +全部最终: + +```text +Adapter + ↓ +Action Runtime + ↓ +Core / App +``` + +--- + +# 40. Core Dependency Rule + +严格规定: + +```text +Foundation + ↑ +Domain + ↑ +Application + ↑ +Adapters +``` + +实际依赖方向: + +```text +Adapters + ↓ +Application + ↓ +Domain + ↓ +Foundation +``` + +Infrastructure 通过 Interface 接入。 + +--- + +# 41. 禁止依赖 + +Core 禁止: + +```text +Core → SEO +Core → CRM +Core → DevOps +Core → Plugin +Core → MCP +Core → Skill +Core → Agent +``` + +反过来允许: + +```text +SEO → Core +CRM → Core +Plugin → Core +MCP → Runtime +Skill → Runtime +Agent → Runtime +``` + +--- + +# 42. 推荐目录结构 + +最终 Core package: + +```text +packages/core/ +│ +├── src/ +│ │ +│ ├── foundation/ +│ │ ├── types/ +│ │ ├── errors/ +│ │ ├── ids/ +│ │ ├── result/ +│ │ └── validation/ +│ │ +│ ├── identity/ +│ │ +│ ├── organization/ +│ │ +│ ├── auth/ +│ │ +│ ├── authorization/ +│ │ +│ ├── resource/ +│ │ +│ ├── action/ +│ │ +│ ├── event/ +│ │ +│ ├── task/ +│ │ +│ ├── job/ +│ │ +│ ├── file/ +│ │ +│ ├── storage/ +│ │ +│ ├── notification/ +│ │ +│ ├── audit/ +│ │ +│ ├── settings/ +│ │ +│ ├── search/ +│ │ +│ ├── config/ +│ │ +│ ├── logging/ +│ │ +│ └── health/ +│ +├── package.json +└── tsconfig.json +``` + +--- + +# 43. Infrastructure Package + +Infrastructure 独立: + +```text +packages/infrastructure/ +│ +├── postgres/ +├── redis/ +├── storage/ +├── queue/ +├── search/ +├── mail/ +├── secrets/ +└── logging/ +``` + +这样未来可以替换 Provider。 + +--- + +# 44. Repository Pattern + +推荐: + +```ts +interface UserRepository { + findById(id: string): Promise + + findByEmail(email: string): Promise + + create(user: User): Promise + + update(user: User): Promise + + delete(id: string): Promise +} +``` + +PostgreSQL: + +```ts +class PostgresUserRepository + implements UserRepository +``` + +Domain 不知道 Prisma。 + +--- + +# 45. Prisma 使用原则 + +如果当前 DevOS 使用 Prisma: + +可以继续使用。 + +但: + +```text +Prisma +``` + +属于 Infrastructure。 + +禁止: + +```ts +import { PrismaClient } from '@prisma/client' +``` + +出现在: + +```text +Domain +Action Definition +Plugin SDK +Application Business Logic +``` + +应该只出现在 Repository / Infrastructure。 + +--- + +# 46. Database Boundary + +数据库分为: + +```text +Core Tables +App Tables +Plugin Tables +``` + +逻辑结构: + +```text +PostgreSQL +│ +├── devos_core +│ +├── app_seo +│ +├── app_devops +│ +└── plugin_xxx +``` + +实际是否使用 PostgreSQL Schema 或 Table Prefix,可以由实现阶段决定。 + +但是逻辑边界必须存在。 + +--- + +# 47. Core Table 原则 + +Core 表只能存: + +```text +Platform State +``` + +例如: + +```text +users +organizations +memberships +roles +permissions +sessions +events +tasks +jobs +files +audit_logs +settings +``` + +Core 不允许出现: + +```text +keywords +backlinks +articles +servers +deployments +orders +``` + +--- + +# 48. Dependency Injection + +Core Service 不应该自己 new Infrastructure。 + +错误: + +```ts +const prisma = new PrismaClient() +``` + +正确: + +```ts +class UserService { + constructor( + private users: UserRepository + ) {} +} +``` + +Application Bootstrap 负责组装: + +```text +Repository + ↓ +Service + ↓ +Runtime +``` + +--- + +# 49. Bootstrap + +DevOS 启动过程: + +```text +Load Config + ↓ +Initialize Infrastructure + ↓ +Initialize Core + ↓ +Register Core Services + ↓ +Initialize Runtime + ↓ +Discover Apps + ↓ +Discover Plugins + ↓ +Register Extensions + ↓ +Start HTTP + ↓ +Start Worker +``` + +--- + +# 50. Core Service Registry + +需要统一 Service Registry。 + +例如: + +```ts +container.register( + 'userRepository', + userRepository +) + +container.register( + 'authorization', + authorizationService +) + +container.register( + 'eventBus', + eventBus +) +``` + +Plugin / App 只能访问公开的 SDK Contract。 + +不要直接访问 Container 内部实现。 + +--- + +# 51. Public API vs Internal API + +Core API 分两级: + +```text +Public +Internal +``` + +Public: + +```text +@devos/core/user +@devos/core/resource +@devos/core/action +@devos/core/events +``` + +Internal: + +```text +@devos/core/internal/* +``` + +Plugin 不得依赖 Internal API。 + +--- + +# 52. Versioning + +Core 必须使用 Semantic Versioning: + +```text +MAJOR.MINOR.PATCH +``` + +例如: + +```text +2.0.0 +2.1.0 +2.1.1 +``` + +原则: + +```text +PATCH +Bug Fix + +MINOR +Backward Compatible Feature + +MAJOR +Breaking Change +``` + +--- + +# 53. Core API Stability + +一旦某个接口进入: + +```text +Public API +``` + +就必须考虑: + +```text +Backward Compatibility +Migration +Deprecation +Documentation +``` + +禁止随意修改。 + +--- + +# 54. Extension Contract + +App / Plugin 只能通过: + +```text +SDK +``` + +使用 DevOS。 + +例如: + +```ts +import { + defineResource, + defineAction, + definePlugin +} from '@devos/sdk' +``` + +而不是: + +```ts +import { + InternalContainer, + PrismaClient, + InternalEventBus +} from '@devos/core/internal' +``` + +--- + +# 55. Core 的“瘦身原则” + +如果一个能力满足: + +```text +只有某个 App 使用 +``` + +默认不进入 Core。 + +如果: + +```text +多个 App 都需要 +``` + +可以考虑 Runtime / Shared Package。 + +如果: + +```text +几乎所有 App 都需要 +``` + +才考虑 Core。 + +决策: + +```text +One App + ↓ +App + +Several Apps + ↓ +Shared Package / Runtime + +Almost Everything + ↓ +Core +``` + +--- + +# 56. Shared Package 与 Core 的区别 + +不要把所有公共代码都塞入 Core。 + +例如: + +```text +@devos/date-utils +@devos/http-client +@devos/crypto +``` + +属于 Shared Libraries。 + +Core 是: + +> 平台业务基础能力。 + +不是: + +> 所有公共 TypeScript 工具的垃圾桶。 + +--- + +# 57. Core Migration Strategy + +现有 DevOS 不允许直接“大爆炸重写”。 + +采用: + +```text +Current DevOS + ↓ +Identify Core Candidates + ↓ +Extract Interfaces + ↓ +Extract Services + ↓ +Move Infrastructure + ↓ +Introduce Runtime + ↓ +Convert Existing Features + ↓ +Remove Duplicates +``` + +--- + +# 58. Migration Priority + +第一批: + +```text +Auth +User +Organization +Permission +Role +Settings +``` + +第二批: + +```text +Resource +Action +Event +Task +Job +``` + +第三批: + +```text +File +Storage +Notification +Audit +Search +``` + +第四批: + +```text +Runtime +Plugin +MCP +Skill +Agent +``` + +--- + +# 59. 旧代码处理原则 + +旧代码如果功能正常: + +不要立即删除。 + +先: + +```text +Wrap +Adapter +Migrate +Deprecate +Remove +``` + +例如: + +```text +LegacyPermissionService + ↓ +PermissionAdapter + ↓ +AuthorizationService +``` + +稳定后再删除 Legacy 实现。 + +--- + +# 60. Core Acceptance Criteria + +Core v2 必须满足: + +### A + +新 App 可以直接使用: + +```text +Auth +User +Organization +Permission +Settings +``` + +无需复制代码。 + +### B + +新 App 可以注册: + +```text +Resource +Action +Event +Task +``` + +### C + +Agent / MCP / UI 可以调用相同 Action。 + +### D + +Core 不依赖任何业务 App。 + +### E + +Core 不直接依赖具体数据库 Provider。 + +### F + +Core 不直接依赖具体 Storage Provider。 + +### G + +Plugin 不需要访问 Core Internal API。 + +### H + +所有敏感操作都可以 Audit。 + +### I + +所有异步执行都可以进入统一 Job Runtime。 + +--- + +# 61. 最终 Core 模型 + +最终: + +```text + DevOS Core + │ + ┌──────────────┬───────┼──────────┬──────────────┐ + │ │ │ │ │ + Identity Authorization Resource Action Event + │ │ │ │ │ + └──────────────┴───────┼──────────┴──────────────┘ + │ + ┌─────────┼─────────┐ + │ │ │ + Task Job Audit + │ │ │ + └─────────┼─────────┘ + │ + Infrastructure + │ + ┌───────────────┼───────────────┐ + │ │ │ + PostgreSQL Redis Storage +``` + +--- + +# 62. Core 最终职责 + +DevOS Core 只回答以下问题: + +```text +Who are you? +你是谁? + +Where do you belong? +你属于哪个组织? + +What can you access? +你可以访问什么? + +What resource exists? +系统里有什么资源? + +What action can be executed? +可以执行什么操作? + +Who executed it? +谁执行了它? + +What happened? +发生了什么? + +What work is running? +当前有什么工作? + +Where is the data stored? +数据在哪里? + +How is the system configured? +系统如何配置? +``` + +业务问题交给 App。 + +--- + +# 63. 一句话架构原则 + +DevOS Core 必须做到: + +> **足够强大,让新 App 不需要重复造基础设施;足够克制,让任何业务都不能污染 Core。** + +--- + +# 64. 下一文档 + +下一份: + +```text +03_RESOURCE_ACTION_MODEL.md +``` + +将详细定义 DevOS 最核心的: + +```text +Resource +Resource Definition +Resource Registry +Action +Action Definition +Action Context +Action Permission +Action Validation +Action Execution +Action Result +Action Error +Action Event +Action Audit +Action Middleware +Action Transaction +Action Idempotency +Action Retry +Action Async Execution +``` + +尤其会解决一个非常重要的问题: + +> **以后 UI、REST API、CLI、MCP、Skill、Agent,到底如何全部调用同一个 Action,而不是重新实现五套业务逻辑。** + +这是 DevOS 能不能真正成为“平台”的关键。 \ No newline at end of file diff --git a/Docs/DevOS-Platform-v2/03_RESOURCE_ACTION_MODEL.md — DevOS Resource & Action 模型.md b/Docs/DevOS-Platform-v2/03_RESOURCE_ACTION_MODEL.md — DevOS Resource & Action 模型.md new file mode 100644 index 0000000..5e907fd --- /dev/null +++ b/Docs/DevOS-Platform-v2/03_RESOURCE_ACTION_MODEL.md — DevOS Resource & Action 模型.md @@ -0,0 +1,3015 @@ +# DevOS Platform v2 +## 03 — Resource & Action Model Specification + +**Document Version:** 2.0 +**Status:** Architecture Specification +**Parent:** `01_ARCHITECTURE.md`, `02_CORE_ARCHITECTURE.md` +**Target:** DevOS Platform v2 +**Implementation Target:** Zcode / AI Coding Agent + +--- + +# 1. 文档目的 + +本文件定义 DevOS v2 的两个核心抽象: + +```text +Resource +Action +``` + +这两个概念是 DevOS Platform 的统一业务执行基础。 + +目标: + +```text +UI +REST API +CLI +MCP +Skill +Agent +Workflow +Plugin +``` + +都不能分别实现业务逻辑。 + +所有业务操作最终应该进入: + +```text +Action Runtime +``` + +统一执行。 + +--- + +# 2. 核心原则 + +DevOS 必须遵守: + +> **Resource 描述“系统中有什么”,Action 描述“可以对它做什么”。** + +例如: + +```text +Resource: + Website + +Actions: + create + read + update + delete + scan + analyze + verify + publish +``` + +--- + +# 3. 为什么不是简单 CRUD + +传统 Admin: + +```text +GET /websites +POST /websites +PUT /websites/:id +DELETE /websites/:id +``` + +只能表达: + +```text +CRUD +``` + +但是现代应用需要: + +```text +scan +analyze +publish +deploy +verify +sync +retry +approve +reject +generate +``` + +因此: + +```text +CRUD +``` + +只是 Action 的一个子集。 + +--- + +# 4. 统一执行模型 + +DevOS 所有执行入口: + +```text + ┌──────────┐ + │ UI │ + └────┬─────┘ + │ +┌──────────┐ │ +│ REST API ├─────────────┤ +└──────────┘ │ + ▼ +┌──────────┐ ┌──────────────┐ +│ CLI ├──────►│ Action │ +└──────────┘ │ Runtime │ + └──────┬───────┘ +┌──────────┐ │ +│ MCP ├──────────────┤ +└──────────┘ │ + │ +┌──────────┐ │ +│ Agent ├──────────────┤ +└──────────┘ │ + │ +┌──────────┐ │ +│ Workflow ├──────────────┘ +└──────────┘ +``` + +最终: + +```text +Input + ↓ +Validation + ↓ +Authorization + ↓ +Action Middleware + ↓ +Action Handler + ↓ +Result + ↓ +Audit + ↓ +Event +``` + +--- + +# 5. Resource 定义 + +Resource 是一个平台级对象类型。 + +接口: + +```ts +interface ResourceDefinition< + T = unknown +> { + type: string + + label: string + + description?: string + + schema: Schema + + actions: ActionDefinition[] + + permissions?: PermissionDefinition[] + + events?: EventDefinition[] + + ui?: ResourceUI +} +``` + +--- + +# 6. Resource Type + +Resource type 必须唯一。 + +推荐: + +```text +. +``` + +例如: + +```text +core.user +core.organization + +project.project + +seo.website +seo.keyword +seo.content + +devops.server +devops.deployment +``` + +禁止使用: + +```text +website +keyword +server +``` + +作为大型平台的全局 Resource Type。 + +--- + +# 7. Resource ID + +Resource ID 在同一 Resource Type 内唯一。 + +例如: + +```text +seo.website +``` + +实例: + +```text +website_01 +website_02 +website_03 +``` + +引用: + +```ts +interface ResourceRef { + type: string + id: string +} +``` + +示例: + +```json +{ + "type": "seo.website", + "id": "website_123" +} +``` + +--- + +# 8. Resource Metadata + +Resource 应提供机器可读 Metadata。 + +例如: + +```ts +const websiteResource = defineResource({ + type: 'seo.website', + + label: 'Website', + + description: 'A website managed by SEO application', + + schema: WebsiteSchema, + + actions: [ + scanWebsite, + analyzeWebsite, + verifyWebsite + ] +}) +``` + +Metadata 可以被: + +```text +UI +CLI +MCP +Agent +Documentation +Search +Admin +``` + +使用。 + +--- + +# 9. Resource Schema + +Resource 必须定义 Schema。 + +推荐: + +```text +Zod +``` + +例如: + +```ts +const WebsiteSchema = z.object({ + id: z.string(), + + organizationId: z.string(), + + domain: z.string(), + + status: z.enum([ + 'active', + 'paused', + 'error' + ]), + + createdAt: z.date(), + updatedAt: z.date() +}) +``` + +Schema 的用途: + +```text +Validation +Documentation +UI Form +MCP Schema +Agent Context +API Schema +``` + +--- + +# 10. Resource 不等于 Database Table + +这是非常重要的规则。 + +Resource: + +```text +Platform Concept +``` + +Database Table: + +```text +Storage Implementation +``` + +二者不要求一一对应。 + +例如: + +```text +Resource: +seo.website +``` + +可以由: + +```text +seo_websites +seo_domains +seo_settings +``` + +多个表组成。 + +因此: + +> Resource 是业务对象抽象,而不是数据库表抽象。 + +--- + +# 11. Resource Registry + +DevOS 必须提供全局 Resource Registry。 + +```ts +interface ResourceRegistry { + register( + resource: ResourceDefinition + ): void + + get( + type: string + ): ResourceDefinition | undefined + + has( + type: string + ): boolean + + list(): ResourceDefinition[] +} +``` + +启动阶段: + +```text +Core + ↓ +Apps + ↓ +Plugins + ↓ +Register Resources +``` + +--- + +# 12. Resource Registration + +Core: + +```ts +registerResource(userResource) +registerResource(organizationResource) +``` + +SEO App: + +```ts +registerResource(websiteResource) +registerResource(keywordResource) +``` + +Plugin: + +```ts +registerResource(backlinkResource) +``` + +最终: + +```text +Resource Registry +├── core.user +├── core.organization +├── seo.website +├── seo.keyword +├── seo.content +└── seo.backlink +``` + +--- + +# 13. Action 定义 + +Action 表示一个可执行操作。 + +```ts +interface ActionDefinition< + TInput = unknown, + TOutput = unknown +> { + id: string + + resource?: string + + name: string + + description?: string + + inputSchema?: Schema + + outputSchema?: Schema + + permission?: string + + mode?: ActionMode + + execute( + context: ActionContext, + input: TInput + ): Promise +} +``` + +--- + +# 14. Action ID + +Action ID 必须全局唯一。 + +推荐: + +```text +. +``` + +例如: + +```text +core.user.create +core.user.update + +seo.website.scan +seo.website.analyze +seo.website.publish + +devops.server.deploy +``` + +--- + +# 15. Action 类型 + +Action 至少分为: + +```text +query +command +job +workflow +``` + +### Query + +读取数据: + +```text +website.get +keyword.list +``` + +### Command + +修改状态: + +```text +website.update +website.publish +``` + +### Job + +后台执行: + +```text +website.scan +content.generate +``` + +### Workflow + +多个 Action 编排: + +```text +website.fullAudit +``` + +--- + +# 16. ActionMode + +建议: + +```ts +type ActionMode = + | 'sync' + | 'async' + | 'stream' +``` + +Sync: + +```text +立即返回结果 +``` + +Async: + +```text +返回 Execution / Job +``` + +Stream: + +```text +持续输出进度 +``` + +--- + +# 17. Action Input + +所有 Action 都必须定义 Input Contract。 + +例如: + +```ts +const ScanWebsiteInput = z.object({ + websiteId: z.string(), + + depth: z.number() + .int() + .min(1) + .max(10) +}) +``` + +调用: + +```json +{ + "websiteId": "website_123", + "depth": 3 +} +``` + +--- + +# 18. Action Output + +Output 同样必须定义 Schema。 + +```ts +const ScanWebsiteOutput = z.object({ + executionId: z.string(), + + pagesScanned: z.number(), + + errors: z.number(), + + score: z.number() +}) +``` + +这使: + +```text +UI +Agent +MCP +CLI +``` + +都可以理解结果。 + +--- + +# 19. Action Context + +Action 永远不能只接受: + +```ts +input +``` + +必须同时接收: + +```ts +context +``` + +定义: + +```ts +interface ActionContext { + requestId: string + + executionId: string + + actor: ActorContext + + organizationId?: string + + permissions: string[] + + signal?: AbortSignal + + metadata: Record +} +``` + +--- + +# 20. Actor + +Action 必须知道是谁执行的。 + +Actor 类型: + +```ts +type ActorContext = + | UserActor + | AgentActor + | ServiceActor + | SystemActor +``` + +例如: + +```ts +{ + type: 'user', + id: 'user_123' +} +``` + +或者: + +```ts +{ + type: 'agent', + id: 'seo-agent' +} +``` + +--- + +# 21. Human 与 Agent 必须统一 + +用户: + +```text +User + ↓ +Action +``` + +Agent: + +```text +Agent + ↓ +Action +``` + +因此 Action 不允许写: + +```ts +if (isAgent) { + bypassPermission() +} +``` + +禁止 Agent 绕过权限。 + +--- + +# 22. Authorization + +Action 执行前必须检查 Permission。 + +例如: + +```text +seo.website.scan +``` + +对应: + +```text +seo.website.scan +``` + +或者: + +```text +seo.website.execute +``` + +由 Permission Policy 决定。 + +--- + +# 23. Authorization 顺序 + +标准执行流程: + +```text +Request + ↓ +Resolve Action + ↓ +Validate Input + ↓ +Resolve Resource + ↓ +Resolve Actor + ↓ +Authorization + ↓ +Middleware + ↓ +Execute +``` + +任何一步失败: + +```text +STOP +``` + +--- + +# 24. Resource-level Authorization + +Action 不应该只检查: + +```text +permission exists +``` + +还需要检查: + +```text +resource scope +``` + +例如: + +```text +user has: +seo.website.update +``` + +但: + +```text +website.organizationId +``` + +必须属于: + +```text +context.organizationId +``` + +否则拒绝。 + +--- + +# 25. Policy + +复杂权限使用 Policy。 + +例如: + +```ts +const WebsiteUpdatePolicy = definePolicy({ + resource: 'seo.website', + + action: 'update', + + check: async ({ + actor, + resource + }) => { + return resource.organizationId + === actor.organizationId + } +}) +``` + +--- + +# 26. Validation + +Action Input: + +```text +Schema Validation +``` + +Resource: + +```text +Resource Validation +``` + +Output: + +```text +Output Validation +``` + +流程: + +```text +Input + ↓ +Input Schema + ↓ +Policy + ↓ +Handler + ↓ +Output Schema +``` + +--- + +# 27. Action Middleware + +Action 支持 Middleware。 + +例如: + +```text +Authorization +Audit +Transaction +RateLimit +Idempotency +Logging +Metrics +Tracing +``` + +执行: + +```text +Action + ↓ +Middleware 1 + ↓ +Middleware 2 + ↓ +Middleware 3 + ↓ +Handler +``` + +--- + +# 28. Middleware 顺序 + +推荐: + +```text +Request ID + ↓ +Authentication + ↓ +Authorization + ↓ +Validation + ↓ +Rate Limit + ↓ +Idempotency + ↓ +Audit Start + ↓ +Transaction + ↓ +Handler + ↓ +Audit Result + ↓ +Event +``` + +--- + +# 29. Action Result + +统一返回: + +```ts +interface ActionResult { + success: boolean + + data?: T + + error?: DevError + + executionId: string + + requestId: string +} +``` + +--- + +# 30. Action Error + +统一错误: + +```text +ACTION_NOT_FOUND +ACTION_INVALID +ACTION_UNAUTHORIZED +ACTION_FORBIDDEN +RESOURCE_NOT_FOUND +RESOURCE_INVALID +ACTION_TIMEOUT +ACTION_CANCELLED +ACTION_CONFLICT +ACTION_RATE_LIMITED +ACTION_FAILED +``` + +--- + +# 31. Action Execution + +Action Runtime 创建 Execution。 + +```ts +interface ActionExecution { + id: string + + actionId: string + + actor: ActorRef + + resource?: ResourceRef + + status: + | 'pending' + | 'running' + | 'completed' + | 'failed' + | 'cancelled' + + startedAt?: Date + + completedAt?: Date + + error?: DevError +} +``` + +--- + +# 32. Execution ID + +每一次 Action 执行必须拥有唯一: + +```text +executionId +``` + +例如: + +```text +exec_01J... +``` + +用于: + +```text +Logs +Audit +Events +Tracing +Job +Agent +Workflow +``` + +--- + +# 33. Request ID vs Execution ID + +两者必须区分。 + +```text +requestId +``` + +表示一次外部请求。 + +```text +executionId +``` + +表示一次 Action 执行。 + +例如: + +```text +HTTP Request + requestId = req_123 + ↓ +Action + executionId = exec_456 + ↓ +Job + executionId = exec_456 +``` + +--- + +# 34. Idempotency + +重要 Action 支持: + +```text +idempotencyKey +``` + +例如: + +```http +Idempotency-Key: xxx +``` + +防止: + +```text +重复支付 +重复发布 +重复部署 +重复创建任务 +``` + +Action 定义: + +```ts +{ + idempotent: true +} +``` + +--- + +# 35. Transaction + +需要数据库一致性的 Action 可以声明: + +```ts +{ + transaction: true +} +``` + +Runtime: + +```text +Begin Transaction + ↓ +Action + ↓ +Commit +``` + +失败: + +```text +Rollback +``` + +--- + +# 36. Async Action + +例如: + +```text +seo.website.scan +``` + +可能需要 30 分钟。 + +调用: + +```text +Action + ↓ +Execution + ↓ +Job + ↓ +Worker +``` + +API 不等待 30 分钟。 + +返回: + +```json +{ + "executionId": "exec_123", + "status": "pending" +} +``` + +--- + +# 37. Action Progress + +Async Action 可以提供 Progress: + +```ts +interface ExecutionProgress { + current: number + total?: number + + percentage?: number + + message?: string +} +``` + +例如: + +```text +Scanning website +127 / 500 pages +25% +``` + +UI 可以实时显示。 + +--- + +# 38. Action Cancellation + +Action 应支持: + +```ts +context.signal +``` + +例如: + +```text +User + ↓ +Cancel + ↓ +AbortSignal + ↓ +Action + ↓ +Worker +``` + +特别适用于: + +```text +Crawler +Agent +Generation +Deployment +Sync +``` + +--- + +# 39. Retry + +Async Action 支持: + +```text +retry +``` + +配置: + +```ts +{ + retry: { + maxAttempts: 3, + backoff: 'exponential' + } +} +``` + +但不是所有 Action 都允许 Retry。 + +例如: + +```text +createPayment +``` + +必须非常谨慎。 + +--- + +# 40. Action Event + +Action 完成后可以产生: + +```text +action.started +action.completed +action.failed +action.cancelled +``` + +以及业务 Event。 + +例如: + +```text +seo.website.scan.completed +``` + +--- + +# 41. Audit + +每次敏感 Action 必须记录: + +```text +actor +action +resource +input +result +executionId +requestId +timestamp +``` + +敏感 Input 必须支持脱敏。 + +例如: + +```text +password +token +secret +apiKey +``` + +禁止写入 Audit。 + +--- + +# 42. Action Visibility + +Action 可以声明: + +```ts +visibility: + | 'public' + | 'internal' + | 'agent' + | 'admin' +``` + +例如: + +```text +public +``` + +允许: + +```text +UI +API +CLI +Agent +``` + +而: + +```text +internal +``` + +只能内部调用。 + +--- + +# 43. Action Capability + +Action 可以声明 Capability: + +```ts +capabilities: [ + 'network.http', + 'filesystem.read' +] +``` + +Runtime 必须检查。 + +这对于: + +```text +Plugin +MCP +Agent +``` + +尤其重要。 + +--- + +# 44. Action 与 Plugin + +Plugin 注册: + +```ts +defineAction({ + id: 'seo.website.scan', + resource: 'seo.website', + + inputSchema: ScanInput, + + outputSchema: ScanOutput, + + execute: scanWebsite +}) +``` + +DevOS Runtime 自动: + +```text +Register + ↓ +Validate + ↓ +Permission + ↓ +Expose +``` + +--- + +# 45. Action 与 MCP + +MCP 不应该自己实现: + +```text +scanWebsite() +``` + +而应该: + +```text +MCP Tool + ↓ +Action Invocation + ↓ +seo.website.scan +``` + +MCP Tool Schema 可以自动从 Action Schema 生成。 + +因此: + +```text +Action Input Schema + ↓ +MCP Tool Schema +``` + +避免维护两套定义。 + +--- + +# 46. Action 与 Agent + +Agent Tool 可以自动映射: + +```text +seo.website.scan +``` + +Agent 获得: + +```text +name +description +inputSchema +permission +``` + +Agent: + +```text +Tool Call + ↓ +Action Runtime +``` + +而不是: + +```text +Agent + ↓ +direct database +``` + +--- + +# 47. Action 与 CLI + +CLI: + +```bash +devos action seo.website.scan \ + --website-id website_123 +``` + +CLI: + +```text +parse arguments + ↓ +Action Input + ↓ +Action Runtime +``` + +同一 Action。 + +--- + +# 48. Action 与 REST + +REST Adapter: + +```http +POST /api/actions/seo.website.scan +``` + +Body: + +```json +{ + "websiteId": "website_123" +} +``` + +最终: + +```text +REST + ↓ +Action Invocation +``` + +--- + +# 49. Action 与 UI + +UI: + +```tsx +await actions.execute( + 'seo.website.scan', + { + websiteId + } +) +``` + +UI 不需要知道: + +```text +API URL +Database +Queue +Worker +``` + +--- + +# 50. Action Client SDK + +SDK: + +```ts +actions.execute( + actionId, + input +) +``` + +返回: + +```ts +Promise> +``` + +异步: + +```ts +actions.executeAsync( + actionId, + input +) +``` + +--- + +# 51. Action Discovery + +Action 必须可发现。 + +```ts +actionRegistry.list() +``` + +返回: + +```json +[ + { + "id": "seo.website.scan", + "resource": "seo.website", + "description": "Scan a website", + "mode": "async" + } +] +``` + +Agent / MCP 可以利用这一能力。 + +--- + +# 52. Action Metadata + +建议: + +```ts +interface ActionMetadata { + id: string + + resource?: string + + name: string + + description: string + + inputSchema?: unknown + + outputSchema?: unknown + + mode: ActionMode + + permission?: string + + dangerous?: boolean + + requiresApproval?: boolean + + idempotent?: boolean + + capabilities?: string[] +} +``` + +--- + +# 53. Dangerous Action + +危险操作必须明确声明: + +```ts +dangerous: true +``` + +例如: + +```text +server.delete +deployment.rollback +website.publish +database.reset +``` + +Agent 执行危险 Action 时可以要求: + +```text +Human Approval +``` + +--- + +# 54. Approval + +Action 可以声明: + +```ts +requiresApproval: true +``` + +执行: + +```text +Agent + ↓ +Action + ↓ +Approval Required + ↓ +User Approval + ↓ +Action Execute +``` + +Approval 本身应该成为平台资源: + +```text +core.approval +``` + +--- + +# 55. Resource Action Matrix + +Resource 可以生成 Action Matrix。 + +例如: + +```text +Website + + User Editor Admin Agent +------------------------------------------------ +read ✓ ✓ ✓ ✓ +update - ✓ ✓ ✓ +scan - ✓ ✓ ✓ +publish - - ✓ approval +delete - - ✓ - +``` + +这可以成为: + +```text +Permission UI +Policy Engine +Agent Capability +``` + +的数据来源。 + +--- + +# 56. Action Composition + +Action 可以调用另一个 Action。 + +但推荐通过 Runtime: + +```text +Action A + ↓ +Action Runtime + ↓ +Action B +``` + +而不是直接: + +```ts +actionB.execute(...) +``` + +这样能够保留: + +```text +Authorization +Audit +Execution +Tracing +Events +``` + +--- + +# 57. Workflow 与 Action + +Workflow 不是特殊的业务逻辑系统。 + +Workflow 由 Action 组成: + +```text +Workflow + ├── Action A + ├── Action B + ├── Action C + └── Action D +``` + +例如: + +```text +Website Audit + +scan + ↓ +analyze + ↓ +generateReport + ↓ +createTasks + ↓ +notify +``` + +--- + +# 58. Action Context Propagation + +Workflow: + +```text +Execution A + ↓ +Execution B + ↓ +Execution C +``` + +必须传播: + +```text +requestId +rootExecutionId +actor +organizationId +traceId +``` + +这样可以追踪完整执行链。 + +--- + +# 59. Root Execution + +复杂 Agent / Workflow 应支持: + +```text +rootExecutionId +parentExecutionId +executionId +``` + +例如: + +```text +root + │ + ├── skill execution + │ │ + │ ├── action A + │ └── action B + │ + └── action C +``` + +--- + +# 60. Action Observability + +每个 Action 必须可以统计: + +```text +execution count +success rate +failure rate +duration +queue time +retry count +``` + +例如: + +```text +seo.website.scan + +Executions: 1,238 +Success: 97.2% +Average: 38s +P95: 91s +``` + +--- + +# 61. Action Rate Limit + +Action 可以定义: + +```ts +rateLimit: { + requests: 100, + window: '1m' +} +``` + +Scope: + +```text +user +organization +ip +agent +plugin +global +``` + +--- + +# 62. Action Timeout + +可以定义: + +```ts +timeout: 30000 +``` + +超时: + +```text +ACTION_TIMEOUT +``` + +Async Job 可以拥有独立 Timeout。 + +--- + +# 63. Resource Lifecycle + +Resource 可以定义: + +```text +created +updated +deleted +archived +restored +``` + +Action 负责状态改变: + +```text +create +update +delete +archive +restore +``` + +Event 负责传播变化: + +```text +resource.created +resource.updated +``` + +--- + +# 64. Soft Delete + +Resource 可以支持: + +```text +active +archived +deleted +``` + +是否 Soft Delete 由 Resource 定义。 + +Core 不强制所有 Resource 使用 Soft Delete。 + +--- + +# 65. Resource Ownership + +Resource 可以声明: + +```ts +ownership: { + organization: true +} +``` + +表示: + +```text +Resource + ↓ +Organization +``` + +Authorization 自动使用 Organization Scope。 + +--- + +# 66. Resource Parent + +支持: + +```text +Project + ↓ +Website + ↓ +Page +``` + +通过 ResourceRef: + +```ts +parent?: ResourceRef +``` + +例如: + +```json +{ + "type": "seo.page", + "id": "page_123", + "parent": { + "type": "seo.website", + "id": "website_456" + } +} +``` + +--- + +# 67. Resource Relationships + +Resource 可以声明: + +```text +belongsTo +hasMany +references +``` + +例如: + +```text +Website + ├── Keywords + ├── Pages + ├── Backlinks + └── Reports +``` + +这些关系可以用于: + +```text +UI +Search +Agent Context +API +``` + +--- + +# 68. Resource UI Metadata + +Resource 可以声明 UI Metadata: + +```ts +ui: { + icon: 'Globe', + + list: { + columns: [...] + }, + + detail: { + sections: [...] + } +} +``` + +这样通用 DevOS UI 可以自动生成部分页面。 + +--- + +# 69. Resource Auto CRUD + +对于简单 Resource: + +```text +create +read +update +delete +``` + +可以通过 Generic CRUD Engine 自动生成。 + +例如: + +```text +Resource Schema + ↓ +Generic CRUD + ↓ +API + ↓ +UI +``` + +但是复杂 Action 必须由业务实现。 + +--- + +# 70. 不允许 Auto CRUD 替代业务 Action + +错误: + +```text +Website Scan +``` + +通过: + +```text +update({ status: 'scanning' }) +``` + +模拟。 + +正确: + +```text +seo.website.scan +``` + +因为 Scan 是真正的业务 Action。 + +--- + +# 71. Action Naming + +Action 命名应该: + +```text +resource.verb +``` + +例如: + +```text +website.create +website.update +website.delete +website.scan +website.verify +website.publish +``` + +不要: + +```text +website.doScanThing +website.handleWebsite +website.process +``` + +--- + +# 72. Action 原子性 + +Action 应尽可能表达一个清晰操作。 + +好: + +```text +website.scan +``` + +不好: + +```text +website.doEverything +``` + +复杂业务应该使用 Workflow。 + +--- + +# 73. Workflow 与“大 Action” + +如果一个操作包含: + +```text +10+ steps +``` + +优先考虑: + +```text +Workflow +``` + +而不是: + +```text +巨大 Action Handler +``` + +--- + +# 74. Action Contract First + +开发业务功能时: + +第一步: + +```text +Define Resource +``` + +第二步: + +```text +Define Action Contract +``` + +第三步: + +```text +Implement Handler +``` + +第四步: + +```text +Expose UI/API/MCP/Agent +``` + +而不是先写: + +```text +React +Controller +Database +``` + +--- + +# 75. Recommended Development Flow + +新功能: + +```text +Requirement + ↓ +Resource + ↓ +Action + ↓ +Permission + ↓ +Schema + ↓ +Handler + ↓ +Event + ↓ +UI + ↓ +API + ↓ +Agent/MCP +``` + +--- + +# 76. Example:SEO Website Scan + +定义: + +```ts +const scanWebsite = defineAction({ + id: 'seo.website.scan', + + resource: 'seo.website', + + mode: 'async', + + inputSchema: z.object({ + websiteId: z.string(), + depth: z.number().default(3) + }), + + outputSchema: z.object({ + executionId: z.string() + }), + + permission: 'seo.website.scan', + + execute: async (ctx, input) => { + // Business implementation + } +}) +``` + +--- + +# 77. 调用方式一:UI + +```ts +await actions.execute( + 'seo.website.scan', + { + websiteId: 'website_123', + depth: 3 + } +) +``` + +--- + +# 78. 调用方式二:REST + +```http +POST /api/actions/seo.website.scan +``` + +```json +{ + "websiteId": "website_123", + "depth": 3 +} +``` + +--- + +# 79. 调用方式三:MCP + +MCP 自动暴露: + +```text +seo.website.scan +``` + +Input Schema: + +```json +{ + "websiteId": "string", + "depth": "number" +} +``` + +MCP 不实现 Scan。 + +--- + +# 80. 调用方式四:Agent + +Agent: + +```text +I need to scan website_123 +``` + +Agent 选择: + +```text +seo.website.scan +``` + +然后: + +```text +Action Runtime +``` + +--- + +# 81. 调用方式五:CLI + +```bash +devos action seo.website.scan \ + --websiteId website_123 \ + --depth 3 +``` + +--- + +# 82. 调用方式六:Workflow + +```text +seo.website.scan + ↓ +seo.website.analyze + ↓ +seo.report.generate +``` + +--- + +# 83. 六种入口,一个实现 + +最终: + +```text + UI + │ +REST ───────────────┤ + │ +CLI ────────────────┤ + ▼ +MCP ───────────► ACTION RUNTIME + ▲ +Agent ─────────────┤ + │ +Workflow ──────────┘ + │ + ▼ + Business Handler +``` + +**绝对禁止维护六套业务实现。** + +--- + +# 84. Action Security Boundary + +所有 Action 必须经过: + +```text +Authentication +Authorization +Validation +Capability Check +Audit +``` + +即使调用来自: + +```text +internal +agent +mcp +system +``` + +也不能默认绕过。 + +只有明确标记: + +```text +trusted internal +``` + +的内部 Action 才可以减少部分检查。 + +--- + +# 85. System Action + +Core 可以拥有 System Action: + +```text +system.cache.clear +system.job.retry +system.plugin.reload +``` + +这些 Action 必须: + +```text +admin-only +audit +dangerous +``` + +--- + +# 86. Action Registration Error + +启动时发现: + +```text +duplicate action id +invalid schema +missing permission +missing resource +invalid dependency +``` + +必须: + +```text +FAIL FAST +``` + +对于严重配置错误: + +```text +Application 不得进入 Ready 状态。 +``` + +--- + +# 87. Resource Registration Error + +同样: + +```text +duplicate resource type +invalid schema +invalid action +``` + +必须阻止对应 Extension 启动。 + +--- + +# 88. Extension Isolation + +Plugin 注册: + +```text +resource +action +event +``` + +只能拥有自己的 namespace。 + +例如: + +```text +plugin.github.* +plugin.cloudflare.* +``` + +不得覆盖: + +```text +core.* +seo.* +``` + +除非通过明确的 Extension Override Contract。 + +--- + +# 89. Override + +默认: + +```text +Override = Forbidden +``` + +未来如需要: + +```text +explicit override +version constraint +compatibility check +``` + +避免 Plugin 悄悄修改核心行为。 + +--- + +# 90. Resource Discovery API + +提供: + +```http +GET /api/resources +``` + +以及: + +```http +GET /api/resources/:type +``` + +用于: + +```text +Admin +Developer Tools +Agent +MCP +Documentation +``` + +--- + +# 91. Action Discovery API + +提供: + +```http +GET /api/actions +``` + +以及: + +```http +GET /api/actions/:id +``` + +可以返回: + +```json +{ + "id": "seo.website.scan", + "resource": "seo.website", + "mode": "async", + "permission": "seo.website.scan", + "inputSchema": {}, + "outputSchema": {} +} +``` + +--- + +# 92. Agent Discovery + +Agent 默认不能看到所有 Action。 + +必须根据: + +```text +Agent Permissions +Organization +Resource Scope +Capabilities +``` + +过滤。 + +最终: + +```text +Available Actions +``` + +是: + +```text +All Actions +∩ +Permission +∩ +Capability +∩ +Scope +``` + +--- + +# 93. MCP Discovery + +MCP 也不能默认暴露全部 Action。 + +必须配置: + +```text +Allowed Actions +``` + +例如: + +```text +MCP Browser + ↓ +network.* +browser.* +``` + +而不能: + +```text +* +``` + +--- + +# 94. Action Approval Model + +危险 Action: + +```text +dangerous = true +``` + +可以进一步: + +```text +approvalPolicy: + always + agent + organization + none +``` + +例如: + +```text +server.delete +``` + +默认: + +```text +always +``` + +--- + +# 95. Action Audit Privacy + +Audit 必须支持: + +```text +redact +hash +omit +``` + +例如: + +```ts +input: { + apiKey: '[REDACTED]' +} +``` + +而不是记录真实 Secret。 + +--- + +# 96. Action Metrics + +每个 Action 自动产生: + +```text +devos_action_total +devos_action_success +devos_action_failure +devos_action_duration +devos_action_queue_duration +``` + +标签: + +```text +actionId +status +app +plugin +``` + +避免将高基数: + +```text +userId +resourceId +``` + +直接作为 Metrics Label。 + +--- + +# 97. Action Logging + +Log 自动包含: + +```text +requestId +executionId +actionId +actorId +organizationId +``` + +业务代码不需要手动重复加入。 + +--- + +# 98. Action Testing + +每个 Action 必须至少拥有: + +```text +Input Validation Test +Authorization Test +Success Test +Failure Test +Audit Test +Event Test +``` + +Async Action 额外: + +```text +Job Dispatch Test +Retry Test +Cancellation Test +``` + +--- + +# 99. Resource Testing + +每个 Resource 至少: + +```text +Schema Test +Registration Test +Permission Test +Action Registration Test +``` + +--- + +# 100. Golden Rule + +DevOS v2 必须始终保持: + +```text +Resource + ↓ +Action + ↓ +Action Runtime +``` + +这是整个 DevOS 的业务执行主干。 + +--- + +# 101. 最终架构 + +```text + ┌──────────────┐ + │ Resource │ + └──────┬───────┘ + │ + ┌──────▼───────┐ + │ Action │ + └──────┬───────┘ + │ + ┌──────▼───────┐ + │ Action │ + │ Runtime │ + └──────┬───────┘ + │ + ┌─────────────────┼─────────────────┐ + │ │ │ + Validation Authorization Policy + │ │ │ + └─────────────────┼─────────────────┘ + │ + ┌──────▼───────┐ + │ Middleware │ + └──────┬───────┘ + │ + ┌──────▼───────┐ + │ Handler │ + └──────┬───────┘ + │ + ┌───────────────┼───────────────┐ + │ │ │ + Audit Event Execution + │ │ │ + └───────────────┼───────────────┘ + │ + ┌──────▼───────┐ + │ Result │ + └──────────────┘ +``` + +--- + +# 102. 最重要的设计结论 + +以后开发 DevOS App 时: + +**不要问:** + +> “我要做一个 API。” + +而应该问: + +> “我要创建什么 Resource?它有哪些 Action?” + +然后: + +```text +Resource ++ +Action ++ +Permission ++ +Schema ++ +Handler +``` + +自然生成: + +```text +API +UI +MCP +Agent Tool +CLI +Workflow +Audit +Events +Metrics +``` + +这就是 DevOS v2 与普通 Admin Framework 最大的区别。 + +--- + +# 103. Implementation Rule for Zcode + +Zcode 实施本规范时: + +1. 不得为 UI 单独实现业务逻辑。 +2. 不得为 REST Controller 单独实现业务逻辑。 +3. 不得为 MCP Tool 单独实现业务逻辑。 +4. 不得为 Agent Tool 单独实现业务逻辑。 +5. 不得为 CLI 单独实现业务逻辑。 +6. 所有业务执行必须进入 Action Runtime。 +7. Action 必须拥有唯一 ID。 +8. Action Input / Output 必须 Schema 化。 +9. Action 必须经过 Authorization。 +10. 敏感 Action 必须 Audit。 +11. Async Action 必须支持 Execution。 +12. Action 必须支持统一错误模型。 +13. Resource 必须通过 Registry 注册。 +14. App / Plugin 必须使用 namespace。 +15. 禁止直接修改其他 Extension 的 Resource / Action。 +16. Agent 与 Human 必须使用相同 Action。 +17. MCP 与 API 必须使用相同 Action。 +18. 复杂多步骤逻辑必须优先使用 Workflow。 +19. Core 不允许依赖业务 Resource。 +20. 任何绕过 Action Runtime 的业务执行代码都应视为架构违规。 + +--- + +# 104. 与后续模块的关系 + +本规范之后: + +```text +04_EVENT_TASK_JOB.md +``` + +定义: + +```text +Event +Task +Job +Execution +Queue +Scheduler +Workflow +``` + +然后: + +```text +05_PLUGIN_SYSTEM.md +``` + +将定义 Plugin 如何注册: + +```text +Resource +Action +Event +Page +Navigation +Settings +Widget +MCP +Skill +``` + +最终形成: + +```text +Plugin + ↓ +Resource + ↓ +Action + ↓ +Runtime +``` + +这将成为 DevOS v2 的标准扩展路径。 \ No newline at end of file diff --git a/Docs/DevOS-Platform-v2/04_EVENT_TASK_JOB.md b/Docs/DevOS-Platform-v2/04_EVENT_TASK_JOB.md new file mode 100644 index 0000000..a08096b --- /dev/null +++ b/Docs/DevOS-Platform-v2/04_EVENT_TASK_JOB.md @@ -0,0 +1,2663 @@ +# `04_EVENT_TASK_JOB.md` + +> DevOS Developer Work OS +> Event / Task / Job / Execution / Queue / Scheduler / Workflow 设计规范 +> Version: 1.0 + +--- + +## 1. 文档目标 + +本模块定义 DevOS 的**异步执行基础设施**。 + +上一份 `03_RESOURCE_ACTION_MODEL.md` 已经确定: + +> 所有业务行为最终都必须进入 `Action Runtime`。 + +但真实系统中,大量 Action 不适合在 HTTP 请求生命周期内直接完成,例如: + +* 扫描网站 +* SSH 执行命令 +* Docker 操作 +* Git Clone +* DNS 检测 +* 批量生成内容 +* 批量外链提交 +* AI Agent 执行任务 +* 定时任务 +* 大规模数据同步 +* 文件处理 +* 部署 +* 监控检查 + +因此 DevOS 必须在 Action Runtime 之上建立统一的: + +```text +Event +Task +Job +Execution +Queue +Scheduler +Workflow +Worker +``` + +体系。 + +核心目标: + +> **任何耗时、可重试、可取消、可恢复、可观察的操作,都必须进入统一 Execution Runtime。** + +--- + +# 2. 核心模型 + +DevOS 不应该把: + +```text +Task +Job +Workflow +Queue +Cron +Agent Task +``` + +设计成互相独立的系统。 + +统一模型: + +```text +Event + ↓ +Trigger + ↓ +Task + ↓ +Workflow + ↓ +Action + ↓ +Execution + ↓ +Job + ↓ +Worker +``` + +其中: + +```text +Task +``` + +是**业务任务**。 + +```text +Execution +``` + +是**一次具体执行实例**。 + +```text +Job +``` + +是进入队列、等待 Worker 执行的工作单元。 + +--- + +# 3. Event + +Event 表示: + +> 系统中已经发生了一件事情。 + +例如: + +```text +user.created +website.created +website.scan.completed +deployment.failed +server.offline +task.completed +plugin.installed +agent.goal.created +``` + +Event 不负责执行。 + +Event 只描述: + +```text +发生了什么 +``` + +--- + +## 3.1 Event 结构 + +```ts +interface DevOSEvent { + id: string + + type: string + + version: number + + timestamp: string + + actor?: Actor + + organizationId?: string + + resource?: { + type: string + id: string + } + + data: T + + metadata?: Record + + correlationId?: string + + causationId?: string +} +``` + +例如: + +```json +{ + "id": "evt_123", + "type": "website.created", + "version": 1, + "timestamp": "2026-09-08T12:00:00Z", + "resource": { + "type": "seo.website", + "id": "web_001" + }, + "data": { + "domain": "example.com" + } +} +``` + +--- + +# 4. Event Bus + +DevOS 使用统一 Event Bus。 + +```text +Action Runtime + │ + ▼ + Event Bus + │ + ┌────┼──────────┐ + ▼ ▼ ▼ +Task Plugin Agent + │ + ▼ +Workflow +``` + +Event Bus 必须支持: + +* publish +* subscribe +* retry +* dead letter +* ordering +* correlation +* tracing + +--- + +## 4.1 Event Handler + +插件可以订阅事件: + +```ts +eventBus.subscribe( + "website.created", + async event => { + // ... + } +) +``` + +但 Handler 不应该直接执行大量业务逻辑。 + +推荐: + +```text +Event Handler + ↓ +Create Task + ↓ +Queue + ↓ +Worker + ↓ +Action +``` + +而不是: + +```text +Event Handler + ↓ +直接执行 30 秒任务 +``` + +--- + +# 5. Task + +Task 表示: + +> 用户、Agent、系统要求完成的一项业务工作。 + +例如: + +```text +扫描 example.com +部署项目 +同步 GitHub Repository +检查服务器 +生成 100 篇文章 +提交 200 个外链 +``` + +Task 是业务层概念。 + +--- + +## 5.1 Task 状态 + +```text +draft +queued +running +waiting +paused +completed +failed +cancelled +``` + +推荐状态机: + +```text +draft + │ + ▼ +queued + │ + ▼ +running + ┌┼───────────────┐ + ▼▼ ▼ +waiting completed + │ + ▼ +running + +running + ├── failed + └── cancelled +``` + +--- + +# 6. Task 数据模型 + +```ts +interface Task { + id: string + + type: string + + name?: string + + description?: string + + status: TaskStatus + + priority: number + + organizationId: string + + projectId?: string + + resource?: ResourceRef + + input?: unknown + + output?: unknown + + createdBy: Actor + + parentTaskId?: string + + workflowId?: string + + createdAt: Date + + startedAt?: Date + + completedAt?: Date + + error?: TaskError +} +``` + +--- + +# 7. Task Type + +Task 必须拥有 namespace。 + +例如: + +```text +core.backup +devops.deploy +devops.server.scan +seo.website.scan +seo.content.generate +seo.link.build +agent.goal.execute +``` + +插件: + +```text +plugin.cloudflare.dns.sync +plugin.github.repository.sync +plugin.wordpress.publish +``` + +--- + +# 8. Job + +Job 是: + +> Task 中需要实际执行的工作单元。 + +一个 Task 可以包含多个 Job。 + +例如: + +```text +Task: +SEO 网站优化 + +Jobs: + ├── Crawl Website + ├── Analyze Keywords + ├── Generate Content + ├── Publish Content + └── Build Backlinks +``` + +因此: + +```text +Task ≠ Job +``` + +--- + +# 9. Job 生命周期 + +```text +pending + ↓ +queued + ↓ +running + ↓ +completed +``` + +异常: + +```text +running + ├── retrying + │ ↓ + │ queued + │ + ├── failed + │ + └── cancelled +``` + +--- + +# 10. Execution + +Execution 是 DevOS 最重要的运行时概念之一。 + +定义: + +> 一个 Action 被实际执行一次,就是一个 Execution。 + +例如: + +```text +Action: +seo.website.scan + +Execution: +exec_123 +``` + +同一个 Action 可以执行: + +```text +exec_001 +exec_002 +exec_003 +``` + +--- + +## 10.1 Execution 数据 + +```ts +interface ActionExecution { + id: string + + actionId: string + + taskId?: string + + jobId?: string + + status: ExecutionStatus + + mode: "sync" | "async" | "stream" + + actor: Actor + + input: unknown + + output?: unknown + + error?: ExecutionError + + progress?: ExecutionProgress + + startedAt?: Date + + completedAt?: Date + + duration?: number + + attempt: number + + maxAttempts: number + + createdAt: Date +} +``` + +--- + +# 11. Task / Job / Execution 的关系 + +必须严格区分: + +```text +Task + │ + ├── Job + │ └── Execution + │ + ├── Job + │ └── Execution + │ + └── Job + └── Execution +``` + +例如: + +```text +Task: 部署网站 + +Job 1: Build +Execution 1 + +Job 2: Upload +Execution 1 + +Job 3: Restart Container +Execution 1 +``` + +如果 Job 重试: + +```text +Job + ├── Execution attempt 1 → failed + ├── Execution attempt 2 → failed + └── Execution attempt 3 → completed +``` + +因此: + +> **Execution 是不可复用的执行记录。** + +--- + +# 12. Queue + +Queue 负责: + +> 把待执行 Job 从生产者传递给 Worker。 + +架构: + +```text +Action Runtime + │ + ▼ + Job + │ + ▼ + Queue + │ + ▼ + Worker + │ + ▼ + Execution +``` + +--- + +# 13. Queue 类型 + +DevOS 初期至少支持: + +```text +default +high +low +scheduled +agent +workflow +``` + +但不要为每种业务创建独立 Queue 系统。 + +应该统一 Queue Runtime: + +```ts +queue.enqueue({ + queue: "default", + jobId, + priority +}) +``` + +--- + +# 14. Worker + +Worker 是真正执行 Job 的进程。 + +```text +┌─────────────────────┐ +│ DevOS API │ +└──────────┬──────────┘ + │ + ▼ + Queue + │ + ┌──────┼──────┐ + ▼ ▼ ▼ + Worker Worker Worker +``` + +Worker: + +1. 获取 Job +2. 创建 Execution +3. 加载 Action +4. 验证 Input +5. 检查权限 +6. 执行 Action +7. 更新 Progress +8. 保存 Result +9. 写 Audit +10. 发布 Event + +--- + +# 15. Worker 不允许绕过 Action Runtime + +这是 DevOS 的核心规则。 + +错误: + +```ts +worker(async job => { + await prisma.website.update(...) +}) +``` + +正确: + +```ts +worker(async job => { + await actionRuntime.execute({ + action: "seo.website.scan", + input: job.input + }) +}) +``` + +也就是说: + +```text +Worker + ↓ +Action Runtime + ↓ +Action +``` + +而不是: + +```text +Worker + ↓ +Database +``` + +--- + +# 16. Retry + +所有异步 Job 必须支持 Retry Policy。 + +```ts +interface RetryPolicy { + maxAttempts: number + + strategy: + | "fixed" + | "linear" + | "exponential" + + delayMs: number + + maxDelayMs?: number + + retryOn?: string[] +} +``` + +例如: + +```json +{ + "maxAttempts": 5, + "strategy": "exponential", + "delayMs": 1000, + "maxDelayMs": 60000 +} +``` + +执行: + +```text +1s +2s +4s +8s +16s +``` + +--- + +# 17. 什么错误可以 Retry + +应该区分: + +### Retryable + +```text +network timeout +connection reset +temporary API failure +rate limit +temporary database error +503 +``` + +### Non-Retryable + +```text +permission denied +invalid input +resource not found +authentication failed +business rule violation +``` + +Action 可以定义: + +```ts +retryableErrors: [ + "NETWORK_TIMEOUT", + "RATE_LIMIT", + "TEMPORARY_UNAVAILABLE" +] +``` + +--- + +# 18. Dead Letter Queue + +超过最大 Retry: + +```text +Job + ↓ +retry + ↓ +retry + ↓ +retry + ↓ +failed + ↓ +DLQ +``` + +Dead Letter Queue 用于: + +* 人工检查 +* Debug +* 恢复 +* 重新执行 + +UI 应提供: + +```text +Failed Jobs + +[Retry] +[Replay] +[Cancel] +[View Error] +[View Logs] +``` + +--- + +# 19. Progress + +长任务必须支持 Progress。 + +```ts +interface ExecutionProgress { + current: number + + total?: number + + percentage?: number + + message?: string + + phase?: string +} +``` + +例如: + +```text +SEO Scan + +Phase: Crawl + +████████████░░░░ 72% + +723 / 1000 pages +``` + +Worker: + +```ts +ctx.progress({ + current: 723, + total: 1000, + phase: "crawl", + message: "Scanning pages" +}) +``` + +--- + +# 20. Cancellation + +Task 必须支持取消。 + +```text +User + ↓ +Cancel Task + ↓ +Task.cancel() + ↓ +AbortSignal + ↓ +Worker + ↓ +Action +``` + +Action Context: + +```ts +interface ActionContext { + signal: AbortSignal +} +``` + +Action: + +```ts +if (ctx.signal.aborted) { + throw new CancelledError() +} +``` + +--- + +# 21. Pause / Resume + +不是所有任务都可以 Pause。 + +Action 可以声明: + +```ts +supportsPause: true +``` + +如果支持: + +```text +running + ↓ +paused + ↓ +running +``` + +如果不支持: + +```text +Cancel ++ +Create new execution +``` + +不要强行模拟所有 Action 都可以暂停。 + +--- + +# 22. Scheduler + +Scheduler 负责: + +> 在指定时间触发 Task。 + +支持: + +```text +once +interval +cron +event-driven +``` + +例如: + +```text +每天 02:00 +每 30 分钟 +每周一 +每次网站创建后 +``` + +--- + +# 23. Schedule + +```ts +interface Schedule { + id: string + + name: string + + actionId?: string + + taskType: string + + scheduleType: + | "once" + | "interval" + | "cron" + | "event" + + expression?: string + + timezone?: string + + enabled: boolean + + input?: unknown + + nextRunAt?: Date + + lastRunAt?: Date +} +``` + +--- + +# 24. Cron + +例如: + +```text +0 2 * * * +``` + +表示: + +```text +每天凌晨 2 点 +``` + +但是: + +> Scheduler 不应该直接执行 Action。 + +必须: + +```text +Scheduler + ↓ +Create Task + ↓ +Create Job + ↓ +Queue + ↓ +Worker + ↓ +Action Runtime +``` + +--- + +# 25. 为什么 Scheduler 不能直接执行 + +错误: + +```text +Cron + ↓ +Action +``` + +正确: + +```text +Cron + ↓ +Task + ↓ +Job + ↓ +Queue + ↓ +Execution +``` + +这样才能获得: + +* Audit +* Retry +* Progress +* Cancellation +* Observability +* History +* Permission +* Agent compatibility + +--- + +# 26. Workflow + +Workflow 是: + +> 多个 Action / Task 按逻辑组合形成的业务流程。 + +例如: + +```text +Website Scan + ↓ +Analyze + ↓ +Generate Report + ↓ +Notify User +``` + +--- + +# 27. Workflow 不应该成为第二套执行引擎 + +这是非常重要的一点。 + +不要实现: + +```text +Action Runtime +Workflow Runtime +Agent Runtime +Plugin Runtime +``` + +四套执行逻辑。 + +正确: + +```text + Workflow + │ + ▼ + Action Runtime + │ + ┌─────┼─────┐ + ▼ ▼ ▼ + Action Action Action +``` + +Workflow 只是**编排层**。 + +--- + +# 28. Workflow Node + +```ts +interface WorkflowNode { + id: string + + type: + | "action" + | "condition" + | "parallel" + | "foreach" + | "wait" + | "approval" + + config: unknown +} +``` + +例如: + +```text +Node A: website.scan +Node B: website.analyze +Node C: condition +Node D: content.generate +Node E: publish +``` + +--- + +# 29. Workflow Edge + +```ts +interface WorkflowEdge { + from: string + + to: string + + condition?: string +} +``` + +形成: + +```text +A +│ +▼ +B +│ +▼ +C +├── true → D +└── false → E +``` + +--- + +# 30. Parallel + +Workflow 必须支持并行。 + +```text + Scan + │ + ┌─────┼─────┐ + ▼ ▼ ▼ + SEO Links Content + │ │ │ + └─────┼─────┘ + ▼ + Report +``` + +--- + +# 31. Foreach + +例如: + +```text +100 Websites +``` + +执行: + +```text +foreach website: + website.scan +``` + +而不是生成一个包含 100 个硬编码节点的 Workflow。 + +--- + +# 32. Approval + +危险操作必须支持人工审批。 + +例如: + +```text +Agent + ↓ +Generate deployment plan + ↓ +Approval + ↓ +Deploy +``` + +或者: + +```text +Agent + ↓ +Build 200 backlinks + ↓ +Approval + ↓ +Execute +``` + +Workflow Node: + +```ts +{ + type: "approval", + config: { + requiredRole: "admin" + } +} +``` + +--- + +# 33. Wait + +Workflow 需要支持等待。 + +例如: + +```text +Deploy + ↓ +Wait 10 minutes + ↓ +Health Check +``` + +不要让 Worker: + +```ts +await sleep(10 * 60 * 1000) +``` + +这会浪费 Worker。 + +应该: + +```text +Workflow + ↓ +Create delayed Job + ↓ +Worker release + ↓ +Queue + ↓ +10 minutes later + ↓ +continue +``` + +--- + +# 34. Event-driven Workflow + +Workflow 可以等待 Event。 + +例如: + +```text +Create Deployment + ↓ +WAIT deployment.completed + ↓ +Run Health Check +``` + +这比轮询更加高效。 + +--- + +# 35. Task 与 Agent + +Agent 不应该拥有独立 Task 系统。 + +正确: + +```text +Agent + ↓ +Goal + ↓ +Plan + ↓ +Task + ↓ +Action + ↓ +Execution +``` + +例如用户: + +```text +让 example.com 在 10 天内提升 SEO +``` + +Agent: + +```text +Goal + ↓ +Plan + ├── Website Scan + ├── Keyword Research + ├── Content Generation + ├── Content Publishing + └── Backlink Building +``` + +这些全部转换为: + +```text +Task +``` + +然后使用统一 Task Runtime。 + +--- + +# 36. Agent 与 Workflow + +Agent 可以动态生成 Workflow。 + +例如: + +```text +Goal + ↓ +Agent Planning + ↓ +Workflow + ↓ +Task + ↓ +Action +``` + +但 Agent 也可以直接创建 Task: + +```text +Agent + ↓ +Task + ↓ +Action +``` + +因此: + +```text +Workflow = 固定/半固定流程 + +Agent = 动态决策 +``` + +两者不是竞争关系。 + +--- + +# 37. Plugin 与 Task + +Plugin 可以注册: + +```text +Action +Resource +Event +Task Type +Workflow Node +Scheduler +UI +``` + +例如 GitHub Plugin: + +```text +plugin.github + ├── Resource + │ └── repository + │ + ├── Action + │ ├── repository.sync + │ ├── repository.create + │ └── repository.dispatch + │ + └── Events + ├── repository.updated + └── workflow.completed +``` + +所有执行仍然经过: + +```text +Action Runtime +``` + +--- + +# 38. MCP 与 Task + +MCP 是能力访问层。 + +例如 MCP Tool: + +```text +seo_scan_website +``` + +不要直接执行: + +```text +MCP + ↓ +HTTP + ↓ +业务代码 +``` + +应该: + +```text +MCP Tool + ↓ +Action + ↓ +Action Runtime + ↓ +Task / Execution +``` + +因此 MCP 只是 Action Runtime 的一个入口。 + +--- + +# 39. CLI + +CLI 同样如此: + +```bash +devos action seo.website.scan +``` + +内部: + +```text +CLI + ↓ +Action Runtime + ↓ +Execution +``` + +--- + +# 40. API + +HTTP: + +```http +POST /api/actions/seo.website.scan +``` + +内部: + +```text +HTTP Controller + ↓ +Action Runtime + ↓ +Execution +``` + +--- + +# 41. UI + +按钮: + +```text +[Scan Website] +``` + +内部: + +```text +UI + ↓ +API + ↓ +Action Runtime + ↓ +Task + ↓ +Job +``` + +--- + +# 42. 所有入口统一 + +最终 DevOS 必须形成: + +```text + ┌── UI + │ + ├── REST API + │ + ├── GraphQL + │ + ├── CLI + │ + ├── MCP + │ + ├── Agent + │ + ├── Plugin + │ + └── Scheduler + │ + ▼ + Action Runtime + │ + ▼ + Task + │ + ▼ + Job + │ + ▼ + Queue + │ + ▼ + Worker + │ + ▼ + Execution + │ + ▼ + Event +``` + +这是 DevOS 最重要的基础设施闭环之一。 + +--- + +# 43. 数据库设计 + +建议 PostgreSQL。 + +核心表: + +```text +events +tasks +jobs +executions +schedules +workflows +workflow_nodes +workflow_edges +task_logs +execution_logs +dead_letter_jobs +``` + +--- + +# 44. Event 表 + +```sql +events +----- +id +type +version +organization_id +actor_type +actor_id +resource_type +resource_id +data +metadata +correlation_id +causation_id +created_at +``` + +--- + +# 45. Task 表 + +```sql +tasks +----- +id +type +name +status +priority +organization_id +project_id +resource_type +resource_id +input +output +created_by +parent_task_id +workflow_id +created_at +started_at +completed_at +error +``` + +--- + +# 46. Job 表 + +```sql +jobs +---- +id +task_id +queue +status +priority +attempt +max_attempts +available_at +started_at +completed_at +worker_id +error +created_at +``` + +--- + +# 47. Execution 表 + +```sql +executions +---------- +id +action_id +task_id +job_id +status +mode +actor +input +output +error +attempt +started_at +completed_at +duration +created_at +``` + +--- + +# 48. Schedule 表 + +```sql +schedules +--------- +id +name +task_type +action_id +schedule_type +expression +timezone +enabled +input +next_run_at +last_run_at +created_at +``` + +--- + +# 49. Log + +日志不要全部塞到 Task 表。 + +单独: + +```text +execution_logs +``` + +例如: + +```ts +interface ExecutionLog { + executionId: string + + level: "debug" | "info" | "warn" | "error" + + message: string + + metadata?: Record + + timestamp: Date +} +``` + +--- + +# 50. Correlation ID + +所有任务链必须支持: + +```text +correlationId +causationId +requestId +executionId +taskId +jobId +``` + +例如: + +```text +HTTP Request +requestId=req_001 + +Agent Goal +correlationId=goal_001 + +Task +taskId=task_001 + +Job +jobId=job_001 + +Execution +executionId=exec_001 +``` + +这样才能追踪完整链路。 + +--- + +# 51. Observability + +每一次 Execution 至少应该能够看到: + +```text +Status +Duration +Worker +Attempts +Input +Output +Error +Logs +Progress +Events +Parent Task +Triggered By +``` + +UI: + +```text +Task Detail +──────────────────────────── + +Status: Running + +Progress: 72% + +Execution + exec_123 + +Attempt: 2 / 5 + +Worker: + worker-03 + +Duration: + 01:23 + +Logs: + ... +``` + +--- + +# 52. Concurrency + +Task / Action 可以定义: + +```ts +concurrency: { + max: 5 +} +``` + +例如: + +```text +SEO Crawl +max concurrency = 5 +``` + +避免: + +```text +1000 websites + ↓ +1000 simultaneous requests + ↓ +system collapse +``` + +--- + +# 53. Resource Lock + +某些 Action 需要锁。 + +例如: + +```text +deploy project A +``` + +同一个 Project 不允许同时: + +```text +deploy A +deploy A +``` + +可以: + +```ts +lock: { + key: "project:{projectId}:deployment" +} +``` + +系统: + +```text +Job A → lock acquired +Job B → waiting +``` + +--- + +# 54. Idempotency + +异步任务必须考虑重复执行。 + +例如: + +```text +publish article +``` + +如果 Worker: + +```text +执行成功 + ↓ +Worker crash + ↓ +没有保存 completed + ↓ +Retry +``` + +可能导致重复发布。 + +因此 Action 应支持: + +```ts +idempotencyKey +``` + +例如: + +```text +publish:{articleId}:{version} +``` + +--- + +# 55. Transaction Boundary + +不要试图把整个异步任务放进一个数据库 Transaction。 + +错误: + +```text +BEGIN + ↓ +HTTP API + ↓ +SSH + ↓ +Docker + ↓ +GitHub + ↓ +COMMIT +``` + +正确: + +```text +DB transaction + ↓ +Create Task + ↓ +COMMIT + +Worker + ↓ +Action + ↓ +external system + ↓ +Save result +``` + +外部系统必须通过: + +```text +idempotency +retry +compensation +``` + +处理一致性。 + +--- + +# 56. Task Result + +Task 最终应该有统一结果: + +```ts +interface TaskResult { + success: boolean + + output?: T + + error?: { + code: string + message: string + details?: unknown + } + + statistics?: { + duration: number + attempts: number + } +} +``` + +--- + +# 57. Event → Task + +系统可以配置: + +```text +Event + ↓ +Trigger Rule + ↓ +Task +``` + +例如: + +```text +deployment.failed + ↓ +create: +monitor.health_check +``` + +或者: + +```text +server.created + ↓ +install: +server.monitor +``` + +--- + +# 58. Trigger + +Trigger 可以有三种: + +```text +Event Trigger +Schedule Trigger +Manual Trigger +``` + +未来可以增加: + +```text +Webhook Trigger +Condition Trigger +Agent Trigger +``` + +统一模型: + +```ts +interface Trigger { + id: string + + type: string + + config: unknown + + enabled: boolean + + target: { + taskType: string + } +} +``` + +--- + +# 59. Task Template + +重复任务应该支持 Template。 + +例如: + +```text +Website Daily SEO Check +``` + +模板: + +```ts +{ + type: "seo.website.daily_check", + + input: { + websiteId: "{{resource.id}}" + } +} +``` + +Scheduler 使用 Template 创建 Task。 + +--- + +# 60. Task Tree + +Task 支持父子关系。 + +```text +SEO Project +│ +├── Website Scan +│ +├── Keyword Research +│ +├── Content +│ ├── Article 1 +│ ├── Article 2 +│ └── Article 3 +│ +└── Backlinks + ├── Link 1 + ├── Link 2 + └── Link 3 +``` + +这样 Agent 可以管理大型任务。 + +--- + +# 61. Task 与 Project + +Project 是 Resource。 + +Task 可以关联 Project: + +```text +Project + │ + ├── Task + ├── Task + └── Task +``` + +因此可以获得: + +```text +Project Dashboard + ├── Running Tasks + ├── Completed Tasks + ├── Failed Tasks + ├── Cost + └── Execution Time +``` + +--- + +# 62. Cost Tracking + +由于未来会有 Agent / AI Task,Execution 应支持 Cost。 + +```ts +interface ExecutionCost { + provider?: string + + model?: string + + inputTokens?: number + + outputTokens?: number + + credits?: number + + money?: number + + currency?: string +} +``` + +这样: + +```text +Project + ↓ +AI Cost + ↓ +$23.51 +``` + +可以统一统计。 + +--- + +# 63. Resource Event + +Resource 的变化应该自动产生 Event。 + +例如: + +```text +Resource: +seo.website + +Action: +update + +Result: +updated + +Event: +seo.website.updated +``` + +这样插件不需要侵入核心业务。 + +--- + +# 64. Event Sourcing + +**第一版不要把 DevOS 做成完整 Event Sourcing 系统。** + +使用: + +```text +State in PostgreSQL ++ +Event Log +``` + +即可。 + +也就是说: + +```text +Database = current state + +Event = historical fact +``` + +未来如果确实需要,再增加 Event Sourcing。 + +--- + +# 65. 推荐基础设施 + +第一阶段: + +```text +PostgreSQL +Redis +Queue +Worker +Scheduler +``` + +如果使用 TypeScript: + +```text +NestJS ++ +BullMQ ++ +Redis ++ +PostgreSQL +``` + +是比较成熟且简单的实现组合。 + +--- + +# 66. BullMQ 的定位 + +如果采用 BullMQ: + +```text +DevOS Queue Runtime + │ + ▼ + BullMQ + │ + ▼ + Redis +``` + +但: + +> DevOS 业务层不能直接依赖 BullMQ API。 + +应该封装: + +```ts +interface QueueRuntime { + enqueue(job: JobPayload): Promise + + cancel(jobId: string): Promise + + retry(jobId: string): Promise + + get(jobId: string): Promise +} +``` + +未来可以替换: + +```text +BullMQ +Temporal +RabbitMQ +SQS +NATS +``` + +而不用修改业务代码。 + +--- + +# 67. 第一版不要引入 Temporal + +Temporal 很强,但 DevOS 第一版不需要立即依赖。 + +建议: + +```text +V1: +BullMQ + Redis + +V2: +根据 Workflow 复杂度决定是否引入 Temporal +``` + +尤其是: + +```text +long-running workflow +durable execution +复杂 compensation +跨服务 workflow +``` + +真正出现需求后再升级。 + +--- + +# 68. Runtime 分层 + +最终后端结构建议: + +```text +apps/ + api/ + worker/ + scheduler/ + +packages/ + core/ + resource/ + action/ + event/ + task/ + execution/ + queue/ + workflow/ + scheduler/ + plugin/ + agent/ + mcp/ +``` + +--- + +# 69. Action Runtime 与 Task Runtime + +职责必须明确: + +```text +Action Runtime += +执行一个 Action +``` + +```text +Task Runtime += +管理一个业务任务 +``` + +```text +Execution Runtime += +记录一次实际执行 +``` + +```text +Queue Runtime += +负责调度工作 +``` + +```text +Workflow Runtime += +编排多个步骤 +``` + +```text +Scheduler += +决定什么时候创建 Task +``` + +--- + +# 70. 最终架构 + +```text + DevOS + │ + ┌─────────────┴─────────────┐ + │ │ + Platform Core Extensions + │ │ + ┌─────────┼─────────┐ ┌──────┼──────┐ + │ │ │ │ │ │ +Resource Action Event SEO GitHub Docker + │ │ │ + └─────────┼─────────┘ + │ + Action Runtime + │ + ┌────┴────┐ + │ │ + Sync Async + │ + Task + │ + Job + │ + Queue + │ + Worker + │ + Execution + │ + Event +``` + +--- + +# 71. 黄金规则 + +DevOS `04` 必须严格遵守以下规则: + +### Rule 1 + +```text +所有异步业务必须通过 Task Runtime +``` + +### Rule 2 + +```text +所有实际执行必须产生 Execution +``` + +### Rule 3 + +```text +所有 Job 必须经过 Queue Runtime +``` + +### Rule 4 + +```text +Worker 不允许直接调用业务 Service +``` + +### Rule 5 + +```text +Scheduler 不允许直接执行 Action +``` + +### Rule 6 + +```text +Workflow 不允许建立第二套 Action 执行机制 +``` + +### Rule 7 + +```text +Agent 不允许建立自己的 Task System +``` + +### Rule 8 + +```text +MCP 不允许绕过 Action Runtime +``` + +### Rule 9 + +```text +Plugin 不允许绕过 Permission / Audit / Execution +``` + +### Rule 10 + +```text +Retry / Cancel / Progress / Audit / Observability +必须成为 Runtime 能力,而不是每个业务自己实现 +``` + +--- + +# 72. Zcode 实现要求 + +Zcode 下一阶段实现必须至少包含: + +```text +packages/task +packages/job +packages/execution +packages/event +packages/queue +packages/worker +packages/scheduler +packages/workflow +``` + +以及: + +```text +apps/api +apps/worker +apps/scheduler +``` + +--- + +## 必须实现的 API + +```text +POST /tasks +GET /tasks +GET /tasks/:id +POST /tasks/:id/cancel +POST /tasks/:id/retry + +GET /executions/:id +GET /executions/:id/logs + +GET /jobs +GET /jobs/:id + +GET /schedules +POST /schedules +PATCH /schedules/:id +DELETE /schedules/:id + +GET /workflows +POST /workflows +GET /workflows/:id +POST /workflows/:id/run +``` + +--- + +# 73. 必须实现的 UI + +DevOS Dashboard 至少提供: + +```text +Tasks + ├── All + ├── Running + ├── Waiting + ├── Completed + ├── Failed + └── Cancelled + +Executions + +Jobs + +Schedules + +Workflows +``` + +Task Detail: + +```text +Overview +Progress +Executions +Logs +Events +Children +Input +Output +Error +``` + +--- + +# 74. 最终目标 + +完成 `04_EVENT_TASK_JOB.md` 后,DevOS 就拥有了一个统一的: + +> **Durable Execution Foundation** + +从此以后: + +```text +SEO +DevOps +Content +CRM +Monitoring +Deployment +Agent +Plugin +MCP +``` + +都不应该自己重新实现: + +```text +Queue +Retry +Scheduler +Worker +Progress +Cancellation +Execution +Task +Workflow +Audit +``` + +而应该直接使用 DevOS Runtime。 + +最终形成: + +```text + DevOS Execution Runtime + │ + ┌───────────────┼────────────────┐ + │ │ │ + Human Agent Scheduler + │ │ │ + └───────────────┼────────────────┘ + ▼ + Task + ▼ + Job + ▼ + Queue + ▼ + Worker + ▼ + Action Runtime + ▼ + Execution + ▼ + Event + ▼ + Plugin / Workflow / Agent +``` + +**这一步完成后,DevOS 才真正从“后台管理系统”开始变成一个可以承载大量应用和 Agent 的通用执行平台。** diff --git a/Docs/DevOS-Platform-v2/05_PLUGIN_RUNTIME.md b/Docs/DevOS-Platform-v2/05_PLUGIN_RUNTIME.md new file mode 100644 index 0000000..c0662e9 --- /dev/null +++ b/Docs/DevOS-Platform-v2/05_PLUGIN_RUNTIME.md @@ -0,0 +1,2597 @@ +# `05_PLUGIN_RUNTIME.md` + +> DevOS Developer Work OS +> Plugin Runtime / Extension System / Plugin UI / Capability / Lifecycle 设计规范 +> Version: 1.0 + +--- + +## 1. 文档目标 + +`05` 定义 DevOS 的统一 **Plugin Runtime**。 + +DevOS 的目标不是把所有功能都写进 Core,而是: + +> **Core 提供稳定的 Runtime,业务能力通过 Plugin 扩展。** + +最终结构: + +```text +DevOS Core +│ +├── Resource Runtime +├── Action Runtime +├── Event Runtime +├── Task Runtime +├── Execution Runtime +├── Plugin Runtime +├── MCP Runtime +├── Skill Runtime +├── Agent Runtime +└── UI Runtime + │ + ▼ + Plugin Extensions +``` + +Plugin 是 DevOS 扩展能力的主要载体。 + +--- + +# 2. Plugin 的定义 + +Plugin 不是简单的: + +```text +npm package +``` + +也不是简单的: + +```text +一个页面 +``` + +而是: + +> **一个可以向 DevOS Runtime 注册能力、资源、动作、事件、任务、UI、MCP、Skill 的可管理扩展单元。** + +例如: + +```text +GitHub Plugin +Cloudflare Plugin +Docker Plugin +WordPress Plugin +SEO Plugin +Google Search Console Plugin +``` + +--- + +# 3. Plugin 的能力模型 + +一个 Plugin 可以包含: + +```text +Plugin +│ +├── Resources +│ +├── Actions +│ +├── Events +│ +├── Tasks +│ +├── Workflows +│ +├── MCP Servers / Tools +│ +├── Skills +│ +├── Agent Capabilities +│ +├── UI Pages +│ +├── Navigation +│ +├── Dashboard Widgets +│ +├── Reports +│ +├── Context Actions +│ +├── Settings +│ +└── Permissions +``` + +但: + +> Plugin 不要求必须拥有所有能力。 + +最小 Plugin 可以只有一个 Action。 + +--- + +# 4. Plugin 与 Core 的关系 + +正确: + +```text +DevOS Core + ↑ + │ Extension API + │ + Plugin +``` + +Plugin 可以依赖 Core: + +```text +Plugin + ↓ +DevOS SDK + ↓ +DevOS Runtime +``` + +但 Core **不能依赖具体 Plugin**。 + +错误: + +```text +Core + └── github + └── cloudflare + └── seo +``` + +正确: + +```text +Core + └── Plugin Runtime + +plugins/ + ├── github + ├── cloudflare + ├── seo + └── docker +``` + +--- + +# 5. Namespace + +每个 Plugin 必须拥有唯一 namespace。 + +例如: + +```text +github +cloudflare +docker +wordpress +seo +``` + +Plugin 内部资源: + +```text +github.repository +github.organization +``` + +Action: + +```text +github.repository.sync +github.repository.create +github.repository.delete +``` + +Event: + +```text +github.repository.updated +github.repository.deleted +``` + +Skill: + +```text +github.repository.manage +``` + +--- + +# 6. Plugin Manifest + +每个 Plugin 必须有: + +```text +plugin.json +``` + +示例: + +```json +{ + "id": "github", + "name": "GitHub", + "version": "1.0.0", + "description": "GitHub integration", + "author": "DevOS", + "runtime": "devos", + "apiVersion": "1", + "permissions": [], + "capabilities": [] +} +``` + +--- + +# 7. 完整 Manifest + +推荐: + +```ts +interface PluginManifest { + id: string + + name: string + + version: string + + description?: string + + author?: PluginAuthor + + homepage?: string + + icon?: string + + apiVersion: string + + runtimeVersion?: string + + entry: PluginEntry + + capabilities?: PluginCapabilities + + permissions?: PluginPermission[] + + dependencies?: PluginDependency[] + + settings?: PluginSettingDefinition[] + + ui?: PluginUIManifest +} +``` + +--- + +# 8. Plugin Entry + +支持: + +```text +backend +frontend +worker +mcp +``` + +例如: + +```json +{ + "entry": { + "server": "./dist/server.js", + "client": "./dist/client.js" + } +} +``` + +--- + +# 9. Plugin 生命周期 + +Plugin 必须拥有生命周期。 + +```text +installed + ↓ +enabled + ↓ +loaded + ↓ +registered + ↓ +active +``` + +停止: + +```text +active + ↓ +disabled + ↓ +unloaded +``` + +卸载: + +```text +disabled + ↓ +uninstalled +``` + +--- + +# 10. Lifecycle Hooks + +Plugin 可以实现: + +```ts +interface Plugin { + onInstall?(ctx: PluginContext): Promise + + onEnable?(ctx: PluginContext): Promise + + onLoad?(ctx: PluginContext): Promise + + onStart?(ctx: PluginContext): Promise + + onDisable?(ctx: PluginContext): Promise + + onUnload?(ctx: PluginContext): Promise + + onUninstall?(ctx: PluginContext): Promise +} +``` + +--- + +# 11. Install 与 Enable 必须分离 + +这是非常重要的设计。 + +```text +Install +``` + +代表: + +> Plugin 已经存在于系统。 + +```text +Enable +``` + +代表: + +> Plugin 当前允许运行。 + +因此: + +```text +Installed ≠ Enabled +``` + +例如: + +```text +GitHub Plugin +Installed: yes +Enabled: no +``` + +不会执行任何 GitHub Action。 + +--- + +# 12. Plugin Registry + +DevOS 必须拥有全局 Plugin Registry: + +```ts +interface PluginRegistry { + register(plugin: Plugin): void + + unregister(pluginId: string): void + + get(pluginId: string): Plugin + + has(pluginId: string): boolean + + list(): Plugin[] +} +``` + +Registry 是 Runtime 的核心入口。 + +--- + +# 13. Plugin Runtime + +Plugin Runtime 负责: + +```text +发现 Plugin +安装 Plugin +验证 Plugin +加载 Plugin +启动 Plugin +注册能力 +管理生命周期 +卸载 Plugin +``` + +架构: + +```text +Plugin Package + ↓ +Plugin Manager + ↓ +Plugin Validator + ↓ +Plugin Loader + ↓ +Plugin Runtime + ↓ +Registry +``` + +--- + +# 14. Plugin Manager + +Plugin Manager 是管理层。 + +职责: + +```text +install() +uninstall() +enable() +disable() +update() +reload() +get() +list() +``` + +API: + +```ts +interface PluginManager { + install(source: PluginSource): Promise + + uninstall(id: string): Promise + + enable(id: string): Promise + + disable(id: string): Promise + + update(id: string): Promise + + reload(id: string): Promise +} +``` + +--- + +# 15. Plugin Source + +支持: + +```text +npm +git +local +url +builtin +``` + +例如: + +```text +@devos/plugin-github +``` + +或者: + +```text +github.com/example/devos-plugin-github +``` + +或者本地: + +```text +./plugins/github +``` + +--- + +# 16. Built-in Plugin + +部分能力可以作为 Built-in Plugin。 + +例如: + +```text +Core + ├── auth + ├── settings + └── audit +``` + +但推荐仍然使用 Plugin API。 + +这样 Core 与 Extension 的边界更清晰。 + +--- + +# 17. Plugin API + +Plugin 不允许直接修改 DevOS 内部模块。 + +错误: + +```ts +plugin.prisma.user.update(...) +``` + +正确: + +```ts +plugin.resources.register(...) +plugin.actions.register(...) +plugin.events.subscribe(...) +``` + +也就是说: + +> Plugin 通过公开 Runtime API 扩展系统。 + +--- + +# 18. Plugin Context + +```ts +interface PluginContext { + pluginId: string + + logger: Logger + + config: PluginConfig + + resources: ResourceRegistry + + actions: ActionRegistry + + events: EventBus + + tasks: TaskRuntime + + queue: QueueRuntime + + workflows: WorkflowRegistry + + permissions: PermissionRegistry + + ui: UIRuntime + + mcp: MCPRuntime + + skills: SkillRuntime +} +``` + +--- + +# 19. Plugin Resource + +Plugin 可以注册 Resource。 + +例如 GitHub: + +```ts +resources.register({ + type: "github.repository", + + schema: repositorySchema, + + actions: [ + "github.repository.sync", + "github.repository.create" + ] +}) +``` + +这样 GitHub Repository 就进入 DevOS Resource Model。 + +--- + +# 20. Plugin Action + +Plugin 可以注册 Action: + +```ts +actions.register({ + id: "github.repository.sync", + + input: schema, + + mode: "async", + + handler: async (input, ctx) => { + // ... + } +}) +``` + +Action 必须遵循 `03_RESOURCE_ACTION_MODEL.md`。 + +--- + +# 21. Plugin Action 不能绕过 Runtime + +Plugin 内部: + +```text +Plugin + ↓ +Action + ↓ +Action Runtime +``` + +不能: + +```text +Plugin + ↓ +direct DB +``` + +不能: + +```text +Plugin + ↓ +direct Queue +``` + +不能: + +```text +Plugin + ↓ +bypass permission +``` + +--- + +# 22. Plugin Event + +Plugin 可以发布: + +```ts +events.publish({ + type: "github.repository.updated", + resource: { + type: "github.repository", + id: repositoryId + }, + data: {} +}) +``` + +也可以订阅: + +```ts +events.subscribe( + "project.created", + handler +) +``` + +--- + +# 23. Plugin Task + +Plugin 可以注册 Task Type: + +```ts +tasks.registerType({ + type: "github.repository.sync", + + action: "github.repository.sync" +}) +``` + +这样 Scheduler / Agent / Workflow 都可以创建: + +```text +github.repository.sync +``` + +--- + +# 24. Plugin Scheduler + +Plugin 可以声明默认 Schedule: + +例如: + +```text +每天同步 GitHub Repository +``` + +但是 Scheduler 仍然属于 DevOS Core。 + +Plugin 只是注册: + +```text +Schedule Template +``` + +而不是创建第二个 Scheduler。 + +--- + +# 25. Plugin Workflow Node + +Plugin 可以提供 Workflow Node: + +```ts +workflows.registerNode({ + type: "github.create_issue" +}) +``` + +Workflow: + +```text +Scan Website + ↓ +Condition + ↓ +github.create_issue + ↓ +Notify +``` + +Node 内部仍然调用 Action Runtime。 + +--- + +# 26. Plugin MCP + +Plugin 可以提供 MCP。 + +例如: + +```text +GitHub Plugin + │ + └── MCP + ├── search_repository + ├── create_issue + └── create_pull_request +``` + +MCP Tool: + +```text +MCP + ↓ +Action + ↓ +Action Runtime +``` + +而不是单独实现业务执行。 + +--- + +# 27. Plugin Skill + +Plugin 可以提供 Skill: + +```text +github.repository.manage +``` + +Skill 描述: + +```text +什么时候使用 +需要什么 Resource +可以使用什么 Action +需要什么权限 +如何完成目标 +``` + +Skill 不应该自己执行底层操作。 + +```text +Skill + ↓ +Action + ↓ +Runtime +``` + +--- + +# 28. Plugin 与 Agent + +Agent 可以发现 Plugin 提供的能力: + +```text +Agent + ↓ +Capability Discovery + ↓ +Plugin + ├── Action + ├── MCP + └── Skill +``` + +例如: + +```text +用户: +把最新代码部署到服务器 +``` + +Agent 发现: + +```text +GitHub Plugin +Docker Plugin +Server Plugin +``` + +组合: + +```text +github.repository.sync + ↓ +docker.build + ↓ +server.deploy +``` + +--- + +# 29. Capability Registry + +因此 DevOS 需要一个统一: + +```text +Capability Registry +``` + +它可以发现: + +```text +Resource +Action +Skill +MCP Tool +Workflow Node +Task Type +``` + +例如: + +```ts +capabilities.search({ + query: "deploy website" +}) +``` + +返回: + +```text +server.deploy +docker.build +github.repository.release +``` + +--- + +# 30. Plugin UI + +这是本设计非常重要的一部分。 + +Plugin 不应该只是后台代码。 + +Plugin 可以拥有自己的 UI。 + +例如 GitHub Plugin: + +```text +GitHub +├── Repositories +├── Issues +├── Pull Requests +├── Actions +└── Settings +``` + +--- + +# 31. Plugin Navigation + +Plugin 可以注册导航: + +```ts +ui.navigation.register({ + id: "github", + label: "GitHub", + icon: "github", + children: [ + { + id: "repositories", + label: "Repositories", + route: "/github/repositories" + } + ] +}) +``` + +DevOS Shell 自动显示。 + +--- + +# 32. Plugin Page + +Plugin 可以提供页面: + +```ts +ui.pages.register({ + route: "/github/repositories", + component: RepositoryPage +}) +``` + +或者: + +```text +/plugin/github/repositories +``` + +具体 URL 由 DevOS UI Router 决定。 + +Plugin 不应该强行替换整个 App Router。 + +--- + +# 33. Plugin Settings + +每个 Plugin 可以拥有自己的 Settings。 + +例如: + +```text +Settings + └── Plugins + └── GitHub + ├── Token + ├── Organization + ├── Default Repository + └── Webhook +``` + +Settings Schema: + +```ts +interface PluginSettingDefinition { + key: string + + type: + | "string" + | "number" + | "boolean" + | "select" + | "secret" + | "json" + + label: string + + description?: string + + default?: unknown + + required?: boolean +} +``` + +--- + +# 34. Secret Settings + +Token / API Key 等: + +```text +type = secret +``` + +不能: + +```text +GET /plugin/settings +``` + +直接返回明文。 + +UI: + +```text +GitHub Token +************ + +[Update] +``` + +后端使用: + +```text +Secret Store +``` + +存储。 + +--- + +# 35. Plugin Dashboard Widget + +Plugin 可以注册 Dashboard Widget。 + +例如: + +```text +GitHub + ├── Open PRs: 12 + ├── Issues: 31 + └── Failed Actions: 2 +``` + +注册: + +```ts +ui.dashboard.registerWidget({ + id: "github.stats", + title: "GitHub", + component: GitHubStatsWidget +}) +``` + +--- + +# 36. Context Action + +Plugin 可以向 Resource 增加上下文操作。 + +例如用户打开: + +```text +github.repository +``` + +出现: + +```text +[Sync] +[Open GitHub] +[Create Issue] +[Deploy] +``` + +但 Context Action 本质仍然是: + +```text +Action +``` + +因此: + +```text +UI Context Action + ↓ +Action Runtime +``` + +--- + +# 37. Report + +Plugin 可以注册 Report: + +```text +SEO Report +GitHub Activity +Server Health +Deployment Report +``` + +例如: + +```ts +ui.reports.register({ + id: "github.activity", + resource: "github.repository" +}) +``` + +Report 数据应该通过 Action / Query Runtime 获取。 + +--- + +# 38. Query 与 Action + +需要区分: + +```text +Query += +读取数据 +``` + +```text +Action += +改变状态 / 执行行为 +``` + +Plugin 可以注册: + +```text +Query +Action +``` + +但 Query 也必须经过: + +```text +Permission +Tenant Scope +Audit / Observability +``` + +--- + +# 39. Plugin Permission + +每个 Plugin 必须声明权限。 + +例如: + +```json +{ + "permissions": [ + "github.repositories.read", + "github.repositories.write", + "github.issues.write" + ] +} +``` + +Permission 必须经过: + +```text +User + ↓ +Role + ↓ +Permission + ↓ +Plugin Capability + ↓ +Action +``` + +--- + +# 40. Plugin Scope + +权限还必须支持 Scope。 + +例如: + +```text +github.repositories.write +``` + +不能代表: + +```text +所有 Repository +``` + +可能限定: + +```text +organization = xxx +repository = xxx +``` + +因此: + +```ts +scope: { + organizationId, + resourceId +} +``` + +--- + +# 41. Plugin Multi-Tenant + +DevOS 是多组织系统时: + +```text +Organization A + └── GitHub Config A + +Organization B + └── GitHub Config B +``` + +Plugin 配置不能默认全局共享。 + +配置应该有 Scope: + +```text +system +organization +project +user +``` + +--- + +# 42. Plugin Config + +```ts +interface PluginConfig { + pluginId: string + + scope: "system" | "organization" | "project" | "user" + + scopeId?: string + + values: Record +} +``` + +例如: + +```text +GitHub Token + +Organization: +acme + +Token: +xxx +``` + +--- + +# 43. Plugin Dependency + +Plugin 可以依赖其他 Plugin: + +```json +{ + "dependencies": { + "docker": "^1.0.0" + } +} +``` + +例如: + +```text +deployment-plugin + ↓ +docker-plugin + ↓ +server-plugin +``` + +Plugin Manager 必须检查依赖。 + +--- + +# 44. Dependency Graph + +安装时: + +```text +Plugin A + ↓ +Plugin B + ↓ +Plugin C +``` + +必须确保: + +```text +C installed +B installed +A installed +``` + +卸载时反向: + +```text +A + ↓ +B + ↓ +C +``` + +如果其他 Plugin 仍然依赖 C: + +```text +❌ Cannot uninstall C +``` + +--- + +# 45. Version Compatibility + +Manifest: + +```json +{ + "apiVersion": "1", + "runtimeVersion": ">=1.0.0 <2.0.0" +} +``` + +Plugin Manager 必须检查。 + +避免: + +```text +DevOS 2.x + ↓ +Old Plugin + ↓ +Runtime crash +``` + +--- + +# 46. Plugin Migration + +Plugin 升级可能有: + +```text +1.0 + ↓ +1.1 + ↓ +2.0 +``` + +支持: + +```ts +migrations: [ + "1.1.0", + "2.0.0" +] +``` + +升级: + +```text +backup + ↓ +migration + ↓ +load + ↓ +health check +``` + +失败: + +```text +rollback +``` + +--- + +# 47. Plugin Health Check + +每个 Plugin 可以实现: + +```ts +healthCheck(): Promise +``` + +结果: + +```text +healthy +degraded +unhealthy +``` + +例如: + +```text +GitHub Plugin + +Status: Healthy + +API: Connected +Token: Valid +Rate Limit: 4921 +``` + +--- + +# 48. Plugin Status + +Plugin UI: + +```text +Plugin +──────────────────── + +GitHub + +Version: +1.4.2 + +Status: +● Enabled + +Health: +● Healthy + +Actions: +12 + +Resources: +3 + +MCP Tools: +8 + +Skills: +4 + +[Settings] +[Disable] +[Update] +[Uninstall] +``` + +--- + +# 49. Plugin Logs + +Plugin 必须拥有: + +```text +plugin logger +``` + +例如: + +```ts +ctx.logger.info("Repository synced", { + repositoryId +}) +``` + +日志必须带: + +```text +pluginId +requestId +taskId +executionId +``` + +--- + +# 50. Plugin Isolation + +第一版不要过度复杂。 + +推荐: + +```text +Trusted Plugin +``` + +运行在: + +```text +同一 Node.js Runtime +``` + +但是: + +```text +API boundary +permission boundary +config boundary +logging boundary +``` + +必须存在。 + +--- + +# 51. Untrusted Plugin + +未来如果允许第三方 Plugin: + +```text +Untrusted Plugin +``` + +建议独立: + +```text +Process +Container +Sandbox +``` + +例如: + +```text +DevOS + │ + ├── Core + │ + └── Plugin Worker + └── Container +``` + +第一版不要为了 Sandbox 把架构搞得过度复杂。 + +但 API 必须预留这个能力。 + +--- + +# 52. Plugin Security + +Plugin 默认: + +```text +不能访问任意文件 +不能直接访问数据库 +不能绕过 Permission +不能读取其他 Plugin Secret +不能修改 Core +``` + +允许的能力: + +```text +Runtime API +Plugin API +Declared Permission +Declared Secret +``` + +--- + +# 53. Plugin UI Security + +Plugin Frontend 不能默认: + +```ts +window.__DEVOS_INTERNAL__ +``` + +直接访问 Core 内部对象。 + +应该: + +```text +Plugin UI + ↓ +DevOS SDK + ↓ +API +``` + +--- + +# 54. Plugin SDK + +开发 Plugin 时: + +```ts +import { + definePlugin, + defineResource, + defineAction +} from "@devos/sdk" +``` + +例如: + +```ts +export default definePlugin({ + id: "github", + + setup(ctx) { + ctx.resources.register(...) + ctx.actions.register(...) + ctx.ui.navigation.register(...) + } +}) +``` + +--- + +# 55. Plugin SDK 的目标 + +Plugin 开发者不需要知道: + +```text +Prisma +BullMQ +Redis +NestJS internals +React Router internals +``` + +只需要使用: + +```text +DevOS SDK +``` + +这也是 DevOS 成为真正“自己的开发框架”的关键。 + +--- + +# 56. Plugin Package + +推荐结构: + +```text +plugins/ +└── github/ + ├── plugin.json + ├── package.json + ├── src/ + │ ├── index.ts + │ ├── manifest.ts + │ ├── resources/ + │ ├── actions/ + │ ├── events/ + │ ├── tasks/ + │ ├── workflows/ + │ ├── mcp/ + │ ├── skills/ + │ ├── ui/ + │ │ ├── pages/ + │ │ ├── widgets/ + │ │ └── navigation/ + │ └── settings/ + └── migrations/ +``` + +--- + +# 57. 推荐 Monorepo + +最终: + +```text +devos/ +│ +├── apps/ +│ ├── api/ +│ ├── web/ +│ ├── worker/ +│ └── scheduler/ +│ +├── packages/ +│ ├── core/ +│ ├── sdk/ +│ ├── resource/ +│ ├── action/ +│ ├── task/ +│ ├── execution/ +│ ├── event/ +│ ├── queue/ +│ ├── workflow/ +│ ├── plugin/ +│ ├── mcp/ +│ ├── skill/ +│ └── agent/ +│ +└── plugins/ + ├── github/ + ├── docker/ + ├── cloudflare/ + └── seo/ +``` + +--- + +# 58. Plugin 不应该直接属于 Apps + +错误: + +```text +apps/api/src/plugins/github +``` + +这样 Plugin 很快会和 API 强耦合。 + +正确: + +```text +plugins/github +``` + +Plugin 是独立一级模块。 + +--- + +# 59. Plugin UI 加载 + +建议: + +```text +DevOS Shell + │ + ├── Core UI + │ + ├── Plugin Manifest + │ + └── Plugin UI Module +``` + +插件可以动态贡献: + +```text +Routes +Navigation +Widgets +Settings +Context Actions +``` + +--- + +# 60. Plugin 页面不能破坏 Shell + +Plugin 页面必须运行在 DevOS Shell: + +```text +┌─────────────────────────────────────┐ +│ DevOS Header │ +├──────────┬──────────────────────────┤ +│ Sidebar │ Plugin Page │ +│ │ │ +│ GitHub │ Repository │ +│ Docker │ │ +│ SEO │ │ +│ │ │ +└──────────┴──────────────────────────┘ +``` + +Plugin 只负责: + +```text +Content +``` + +Shell 仍然属于 Core。 + +--- + +# 61. Plugin Settings 页面 + +Core 提供通用 Settings Shell: + +```text +Settings +│ +├── General +├── Security +├── Users +│ +└── Plugins + ├── GitHub + ├── Docker + ├── Cloudflare + └── SEO +``` + +Plugin 只需要提供: + +```text +Settings Schema +Settings UI +``` + +--- + +# 62. Plugin Install UI + +DevOS 应提供: + +```text +Plugin Marketplace +``` + +但 Marketplace 不是 Plugin Runtime 本身。 + +可以: + +```text +Marketplace + ↓ +Plugin Package + ↓ +Plugin Manager +``` + +未来可以支持: + +```text +Official +Community +Private +Local +Git +NPM +``` + +--- + +# 63. Plugin Marketplace + +Plugin 页面: + +```text +GitHub +──────────────────── + +Official + +Version 1.4.2 + +★ 4.9 + +Resources: 3 +Actions: 12 +MCP: 8 +Skills: 4 + +[Install] +``` + +安装后: + +```text +[Enable] +``` + +--- + +# 64. Plugin Manifest 与 Marketplace Metadata + +必须分离。 + +Manifest: + +```text +Runtime required data +``` + +Marketplace metadata: + +```text +Description +Screenshots +README +Author +Rating +Downloads +Documentation +``` + +不要让 Runtime 依赖 Marketplace。 + +--- + +# 65. Plugin Registry 数据库 + +建议: + +```text +plugins +plugin_versions +plugin_configs +plugin_permissions +plugin_dependencies +plugin_migrations +``` + +--- + +# 66. Plugin 表 + +```sql +plugins +------- +id +name +version +status +enabled +source +manifest +installed_at +updated_at +``` + +--- + +# 67. Plugin Config 表 + +```sql +plugin_configs +-------------- +id +plugin_id +scope +scope_id +config +created_at +updated_at +``` + +Secret 不应该直接以普通 JSON 保存。 + +--- + +# 68. Plugin Permission 表 + +```sql +plugin_permissions +------------------ +id +plugin_id +permission +scope +created_at +``` + +--- + +# 69. Plugin Event + +Plugin 生命周期本身也应该发布 Event: + +```text +plugin.installed +plugin.enabled +plugin.disabled +plugin.updated +plugin.uninstalled +plugin.failed +``` + +这样其他模块可以监听。 + +--- + +# 70. Plugin Failure + +Plugin 启动失败: + +```text +Plugin + ↓ +Load + ↓ +Error + ↓ +status = failed +``` + +不能导致整个 DevOS Crash。 + +理想: + +```text +Core → Running +GitHub → Failed +Docker → Running +SEO → Running +``` + +--- + +# 71. Plugin Reload + +开发环境支持: + +```text +Hot Reload +``` + +生产环境建议: + +```text +Disable + ↓ +Unload + ↓ +Update + ↓ +Load + ↓ +Enable +``` + +避免运行中的状态污染。 + +--- + +# 72. Plugin Development Mode + +开发者可以: + +```bash +devos plugin dev ./plugins/github +``` + +支持: + +```text +watch +reload +logs +inspect +``` + +--- + +# 73. Plugin CLI + +DevOS 应提供: + +```bash +devos plugin list +devos plugin install github +devos plugin enable github +devos plugin disable github +devos plugin update github +devos plugin remove github +devos plugin inspect github +``` + +--- + +# 74. Plugin Generator + +这对“自己的开发框架”非常重要。 + +提供: + +```bash +devos create plugin github +``` + +自动生成: + +```text +plugin.json +package.json +src/index.ts +src/actions/ +src/resources/ +src/events/ +src/ui/ +src/mcp/ +src/skills/ +``` + +这样未来开发任何项目都可以快速扩展。 + +--- + +# 75. Plugin 类型 + +建议定义: + +```text +integration +domain +developer +ui +agent +infrastructure +``` + +但这些只是 metadata。 + +不要为每种类型建立不同 Runtime。 + +--- + +# 76. Domain Plugin + +例如: + +```text +SEO Plugin +CRM Plugin +Content Plugin +``` + +可以拥有: + +```text +Resource +Action +Task +Workflow +UI +Skill +MCP +``` + +因此 SEO 不需要变成: + +```text +seo-infra +seo-backend +seo-agent +seo-mcp +``` + +而可以是: + +```text +seo plugin +``` + +运行在 DevOS Runtime 上。 + +--- + +# 77. 一个完整 Plugin 示例 + +```text +seo +│ +├── Resources +│ ├── seo.website +│ ├── seo.keyword +│ ├── seo.content +│ └── seo.backlink +│ +├── Actions +│ ├── seo.website.scan +│ ├── seo.keyword.research +│ ├── seo.content.generate +│ └── seo.backlink.submit +│ +├── Tasks +│ ├── seo.website.audit +│ └── seo.campaign.execute +│ +├── Workflows +│ └── seo.campaign +│ +├── MCP +│ └── seo tools +│ +├── Skills +│ ├── seo.audit +│ └── seo.campaign +│ +└── UI + ├── Dashboard + ├── Websites + ├── Keywords + ├── Content + ├── Backlinks + └── Reports +``` + +这就是: + +> **一个产品能力,而不是多个产品。** + +--- + +# 78. Plugin 与 Fork + +DevOS 必须同时支持两种模式。 + +## Extension Mode + +```text +DevOS + └── Plugin +``` + +适合: + +```text +SEO +GitHub +Docker +Cloudflare +Monitoring +``` + +--- + +## Fork Mode + +```text +DevOS Starter + ↓ +Fork + ↓ +独立 App +``` + +适合: + +```text +完全独立 SaaS +不同业务模型 +不同部署生命周期 +不同数据库 +不同团队 +``` + +这两个模式必须从架构层面同时支持。 + +--- + +# 79. Core / Plugin / App 三层 + +最终: + +```text +┌──────────────────────────────┐ +│ App │ +│ │ +│ Product-specific logic │ +└───────────────┬──────────────┘ + │ +┌───────────────▼──────────────┐ +│ Plugins │ +│ │ +│ Domain / Integration │ +└───────────────┬──────────────┘ + │ +┌───────────────▼──────────────┐ +│ DevOS Core │ +│ │ +│ Resource / Action / Task │ +│ Event / Queue / Agent / MCP │ +└──────────────────────────────┘ +``` + +--- + +# 80. 黄金规则 + +### Rule 1 + +```text +Plugin 是扩展,不是 Core +``` + +### Rule 2 + +```text +Plugin 不允许直接修改 Core +``` + +### Rule 3 + +```text +Plugin 所有业务操作必须经过 Action Runtime +``` + +### Rule 4 + +```text +Plugin 所有异步操作必须经过 Task Runtime +``` + +### Rule 5 + +```text +Plugin 不允许创建自己的 Queue / Worker / Scheduler +``` + +### Rule 6 + +```text +Plugin UI 必须运行在 DevOS Shell +``` + +### Rule 7 + +```text +Plugin MCP 必须映射到 Action / Capability +``` + +### Rule 8 + +```text +Plugin Skill 不执行底层业务 +``` + +### Rule 9 + +```text +Plugin 配置必须支持 scope +``` + +### Rule 10 + +```text +Plugin Secret 必须进入 Secret Store +``` + +### Rule 11 + +```text +Plugin 必须声明权限 +``` + +### Rule 12 + +```text +Plugin 生命周期必须由 Plugin Manager 管理 +``` + +--- + +# 81. Zcode 实现要求 + +下一阶段必须实现: + +```text +packages/plugin/ +packages/plugin-sdk/ +packages/capability/ +``` + +至少包含: + +```text +PluginManager +PluginRegistry +PluginLoader +PluginValidator +PluginLifecycle +PluginConfig +PluginPermission +PluginHealth +``` + +--- + +## Plugin API + +```text +POST /plugins/install +POST /plugins/:id/enable +POST /plugins/:id/disable +POST /plugins/:id/update +DELETE /plugins/:id + +GET /plugins +GET /plugins/:id +GET /plugins/:id/health +GET /plugins/:id/settings +PATCH /plugins/:id/settings +``` + +--- + +## Plugin UI + +至少实现: + +```text +/ plugins +/ plugins/:id +/ plugins/:id/settings +``` + +并支持: + +```text +Install +Enable +Disable +Update +Uninstall +Health +Settings +``` + +--- + +# 82. 关键验收标准 + +Zcode 完成 `05` 后,必须可以演示: + +### Demo 1 + +安装 Plugin: + +```text +Install GitHub Plugin +``` + +### Demo 2 + +启用: + +```text +Enable GitHub +``` + +### Demo 3 + +Plugin 自动出现: + +```text +GitHub + ├── Repositories + ├── Issues + └── Settings +``` + +### Demo 4 + +Repository 页面: + +```text +[Sync] +``` + +点击: + +```text +UI + ↓ +Action + ↓ +Task + ↓ +Job + ↓ +Queue + ↓ +Worker + ↓ +Execution +``` + +### Demo 5 + +MCP: + +```text +Agent + ↓ +GitHub MCP + ↓ +github.repository.sync + ↓ +Action Runtime +``` + +### Demo 6 + +Agent: + +```text +Agent + ↓ +Discover Capability + ↓ +GitHub Skill + ↓ +GitHub Action +``` + +### Demo 7 + +Plugin 禁用: + +```text +Disable GitHub +``` + +之后: + +```text +GitHub Actions +GitHub MCP +GitHub Skills +GitHub UI +``` + +全部进入 Disabled 状态。 + +--- + +# 83. 最终 Plugin 架构 + +完成 `05` 后,DevOS 的结构应该变成: + +```text + DevOS + │ + ┌──────────────┴──────────────┐ + │ │ + Core Runtime Plugin Runtime + │ │ + ┌───────┼────────┐ ┌─────────┼─────────┐ + │ │ │ │ │ │ + Resource Action Event Plugin Plugin Plugin + │ │ │ │ │ │ + └───────┼────────┘ GitHub Docker SEO + │ + Task Runtime + │ + Execution + │ + Queue/Worker + │ + ┌─────┴─────┐ + │ │ + MCP Agent + │ │ + └─────┬─────┘ + │ + Capability + │ + Skills +``` + +最终形成一个非常关键的原则: + +> **DevOS Core 不负责“拥有所有功能”,而负责“让任何功能都能以统一方式进入系统”。** + +这才是 DevOS 从一个项目逐渐成为你自己的**通用开发框架 / Application Runtime / Agent Platform**的关键。 diff --git a/Docs/DevOS-Platform-v2/06_MCP_SKILL_AGENT_RUNTIME.md b/Docs/DevOS-Platform-v2/06_MCP_SKILL_AGENT_RUNTIME.md new file mode 100644 index 0000000..76ad3b8 --- /dev/null +++ b/Docs/DevOS-Platform-v2/06_MCP_SKILL_AGENT_RUNTIME.md @@ -0,0 +1,3236 @@ +# `06_MCP_SKILL_AGENT_RUNTIME.md` + +> DevOS Developer Work OS +> MCP / Skill / Capability / Agent Runtime 设计规范 +> Version: 1.0 + +--- + +# 1. 文档目标 + +`06` 定义 DevOS 的 **AI Capability Runtime**。 + +前面的架构已经确定: + +```text +03 Resource / Action +04 Task / Job / Execution +05 Plugin Runtime +``` + +现在需要解决: + +> **Agent 到底如何发现能力、理解能力、规划任务、调用工具并持续执行?** + +核心目标不是再做一个“聊天机器人”。 + +而是建立: + +```text +Capability + ↓ +Skill + ↓ +Agent + ↓ +Plan + ↓ +Task + ↓ +Action + ↓ +Execution +``` + +同时支持: + +```text +MCP +Plugin +Skill +Workflow +Human +``` + +统一进入同一个 Runtime。 + +--- + +# 2. 最重要的架构原则 + +DevOS 必须严格区分: + +```text +MCP +Skill +Action +Agent +``` + +它们不是同一个东西。 + +--- + +## MCP + +> **如何访问外部能力。** + +例如: + +```text +GitHub MCP +Cloudflare MCP +Browser MCP +Search MCP +``` + +--- + +## Action + +> **系统真正可以执行的原子行为。** + +例如: + +```text +github.repository.create +website.scan +server.deploy +article.publish +``` + +--- + +## Skill + +> **告诉 Agent 如何完成一类目标。** + +例如: + +```text +seo.website.audit +seo.campaign.execute +github.repository.manage +deploy.application +``` + +--- + +## Agent + +> **根据 Goal 动态决定使用哪些 Skill / Action / Resource。** + +因此: + +```text +MCP ≠ Skill +Skill ≠ Action +Action ≠ Agent +``` + +--- + +# 3. 四层架构 + +DevOS AI Runtime: + +```text +┌──────────────────────────────┐ +│ Agent │ +│ Goal / Planning │ +└──────────────┬───────────────┘ + │ +┌──────────────▼───────────────┐ +│ Skill │ +│ Domain Knowledge │ +└──────────────┬───────────────┘ + │ +┌──────────────▼───────────────┐ +│ Capability │ +│ Action / MCP / Resource │ +└──────────────┬───────────────┘ + │ +┌──────────────▼───────────────┐ +│ DevOS Runtime │ +│ Permission / Task / Queue │ +└──────────────────────────────┘ +``` + +--- + +# 4. Capability + +Capability 是 Agent 能看到的: + +> **“系统能做什么”的统一描述。** + +Capability 可以来自: + +```text +Core +Plugin +MCP +Action +Skill +Workflow +``` + +--- + +# 5. Capability Registry + +DevOS 必须建立: + +```text +Capability Registry +``` + +例如: + +```text +capabilities +├── actions +├── resources +├── skills +├── mcp-tools +└── workflows +``` + +统一搜索: + +```ts +capabilityRegistry.search({ + query: "deploy website" +}) +``` + +返回: + +```text +server.deploy +docker.build +github.repository.release +``` + +--- + +# 6. Capability 数据模型 + +```ts +interface Capability { + id: string + + type: + | "action" + | "skill" + | "mcp_tool" + | "workflow" + | "resource" + + name: string + + description: string + + namespace: string + + inputSchema?: unknown + + outputSchema?: unknown + + permissions?: string[] + + source: { + type: "core" | "plugin" | "mcp" + id: string + } + + metadata?: Record +} +``` + +--- + +# 7. Capability Discovery + +Agent 不应该把所有工具一次性塞进 LLM Context。 + +错误: + +```text +5000 tools + ↓ +全部发送给模型 +``` + +这会导致: + +```text +Token 巨大 +成本高 +模型选择能力下降 +``` + +正确: + +```text +Goal + ↓ +Capability Search + ↓ +Top relevant capabilities + ↓ +LLM +``` + +--- + +# 8. 两阶段 Discovery + +推荐: + +```text +Phase 1: +Semantic Search + +Phase 2: +Permission / Scope Filtering +``` + +流程: + +```text +Goal + ↓ +Search + ↓ +Candidate Capabilities + ↓ +Permission + ↓ +Scope + ↓ +Availability + ↓ +Final Capabilities +``` + +--- + +# 9. Capability Search + +例如: + +```text +Goal: +“把最新 GitHub 项目部署到服务器” +``` + +搜索: + +```text +deploy +github +repository +docker +server +``` + +候选: + +```text +github.repository.get +github.repository.release +docker.build +server.deploy +server.health_check +``` + +Agent 才看到这些能力。 + +--- + +# 10. Token-Efficient Discovery + +这是 DevOS Agent Runtime 的重点。 + +不要发送: + +```text +完整 JSON Schema +完整 Plugin Manifest +完整 README +完整文档 +``` + +第一阶段只返回: + +```text +id +name +description +type +required permission +``` + +例如: + +```json +{ + "id": "server.deploy", + "name": "Deploy Application", + "description": "Deploy an application to a server", + "type": "action" +} +``` + +模型决定需要后,再获取详细 Schema。 + +--- + +# 11. Progressive Disclosure + +能力信息分层: + +```text +Level 1 +Capability Summary + +Level 2 +Capability Schema + +Level 3 +Skill Instructions + +Level 4 +Execution Context +``` + +例如: + +```text +Agent + ↓ +“我需要部署” + ↓ +发现 server.deploy + ↓ +获取 schema + ↓ +生成 input + ↓ +执行 +``` + +--- + +# 12. Skill + +Skill 是 Agent 的: + +> **任务解决方法 / 专业流程 / 决策指南。** + +Skill 不应该成为一个新的执行 Runtime。 + +--- + +# 13. Skill 示例 + +```text +seo.website.audit +``` + +描述: + +```text +目标: +完成网站 SEO 审计。 + +输入: +website + +步骤: +1. 获取网站 +2. Crawl +3. 技术 SEO 分析 +4. 内容分析 +5. Backlink 分析 +6. 生成报告 + +使用能力: +website.scan +seo.keyword.analyze +seo.backlink.analyze +report.generate +``` + +--- + +# 14. Skill Manifest + +```ts +interface SkillManifest { + id: string + + name: string + + description: string + + version: string + + inputs?: unknown + + outputs?: unknown + + requiredCapabilities?: string[] + + instructions?: string + + examples?: SkillExample[] + + metadata?: Record +} +``` + +--- + +# 15. Skill 不应该直接执行代码 + +错误: + +```text +Skill + ↓ +直接调用 API +``` + +正确: + +```text +Skill + ↓ +选择 Capability + ↓ +Action Runtime +``` + +因此 Skill 是: + +```text +Knowledge + Strategy +``` + +而不是: + +```text +Execution Engine +``` + +--- + +# 16. Skill 来源 + +Skill 可以来自: + +```text +Core +Plugin +Project +User +Agent +Marketplace +``` + +例如: + +```text +skills/ +├── core/ +├── seo/ +├── github/ +├── devops/ +└── custom/ +``` + +--- + +# 17. Skill Scope + +Skill 也支持 Scope: + +```text +global +organization +project +user +``` + +例如某个项目可以有: + +```text +project.deploy.production +``` + +只适用于该项目。 + +--- + +# 18. Skill 与 Plugin + +Plugin: + +> 提供能力。 + +Skill: + +> 教 Agent 如何使用这些能力。 + +例如: + +```text +GitHub Plugin +│ +├── github.repository.sync +├── github.repository.create +└── github.issue.create + +GitHub Skill +│ +└── github.repository.manage +``` + +这两个应该分开。 + +--- + +# 19. MCP + +MCP 是 DevOS 与外部 Agent / Tool Ecosystem 之间的标准能力接口。 + +DevOS 可以: + +```text +作为 MCP Client +``` + +也可以: + +```text +作为 MCP Server +``` + +--- + +# 20. DevOS 作为 MCP Client + +例如: + +```text +DevOS + ↓ +External MCP + ↓ +Browser +``` + +或者: + +```text +DevOS + ↓ +Search MCP +``` + +--- + +# 21. DevOS 作为 MCP Server + +外部 Agent: + +```text +Claude +Cursor +其他 Agent +``` + +可以连接: + +```text +DevOS MCP Server +``` + +获得: + +```text +Resources +Actions +Skills +Tasks +``` + +--- + +# 22. MCP Tool 映射 + +最重要规则: + +> **MCP Tool 必须尽可能映射到 DevOS Capability。** + +例如: + +```text +MCP: +create_github_issue +``` + +映射: + +```text +github.issue.create +``` + +调用: + +```text +MCP + ↓ +Capability + ↓ +Action Runtime +``` + +--- + +# 23. MCP 不允许绕过权限 + +即使调用来源是外部 Agent: + +```text +External Agent + ↓ +MCP +``` + +仍然: + +```text +Authentication + ↓ +Authorization + ↓ +Scope + ↓ +Action + ↓ +Audit +``` + +绝不能: + +```text +MCP + ↓ +direct database +``` + +--- + +# 24. MCP Server + +DevOS MCP Server: + +```text +/api/mcp +``` + +提供: + +```text +tools +resources +prompts +``` + +但是不要默认暴露整个 DevOS。 + +必须经过: + +```text +Capability Filter +``` + +--- + +# 25. MCP Capability Filter + +根据: + +```text +Actor +Organization +Project +Permission +Scope +Plugin Status +``` + +过滤。 + +例如: + +```text +Admin +→ 100 tools + +Normal User +→ 30 tools + +Agent +→ 15 tools +``` + +--- + +# 26. Agent + +Agent 是: + +> **Goal-driven Decision & Execution Runtime。** + +Agent 不只是: + +```text +LLM + Prompt +``` + +而应该拥有: + +```text +Goal +Memory +Context +Planning +Capability Discovery +Execution +Observation +Reflection +Retry +Approval +``` + +--- + +# 27. Agent Runtime + +```text +┌─────────────────────────────┐ +│ Agent Runtime │ +├─────────────────────────────┤ +│ Goal │ +│ Context │ +│ Memory │ +│ Planner │ +│ Capability Discovery │ +│ Executor │ +│ Observer │ +│ Evaluator │ +│ Approval │ +└─────────────────────────────┘ +``` + +--- + +# 28. Agent Goal + +```ts +interface AgentGoal { + id: string + + description: string + + actor: Actor + + organizationId: string + + projectId?: string + + status: + | "pending" + | "planning" + | "executing" + | "waiting" + | "completed" + | "failed" + | "cancelled" + + constraints?: Record + + createdAt: Date +} +``` + +--- + +# 29. Goal 示例 + +用户: + +```text +10天内让 a.com 获得100篇软文和200个外链。 +``` + +Agent 不应该直接: + +```text +调用 SEO Tool +``` + +而应该: + +```text +Goal + ↓ +Understand + ↓ +Discover Skills + ↓ +Discover Capabilities + ↓ +Plan + ↓ +Approval if needed + ↓ +Tasks + ↓ +Execute + ↓ +Observe + ↓ +Verify + ↓ +Report +``` + +--- + +# 30. Agent Plan + +Plan 是 Agent 对 Goal 的执行计划。 + +```ts +interface AgentPlan { + id: string + + goalId: string + + steps: AgentPlanStep[] + + status: string +} +``` + +Step: + +```ts +interface AgentPlanStep { + id: string + + type: + | "action" + | "task" + | "workflow" + | "approval" + | "condition" + + capabilityId: string + + input?: unknown + + dependsOn?: string[] + + status: string +} +``` + +--- + +# 31. Agent Plan 示例 + +```text +Goal +│ +├── Step 1 +│ seo.website.scan +│ +├── Step 2 +│ seo.keyword.research +│ +├── Step 3 +│ seo.content.generate +│ +├── Step 4 +│ seo.content.publish +│ +└── Step 5 + seo.backlink.submit +``` + +--- + +# 32. Plan 不等于 Workflow + +两者必须区分。 + +```text +Workflow += +预先定义的流程 +``` + +```text +Agent Plan += +Agent 根据当前 Goal 动态产生的计划 +``` + +例如: + +```text +Workflow: +A → B → C +``` + +Agent: + +```text +Goal + ↓ +发现情况 + ↓ +A + ↓ +观察结果 + ↓ +决定 B 或 D + ↓ +继续 +``` + +--- + +# 33. Agent Loop + +Agent Runtime 核心: + +```text +Observe + ↓ +Think / Plan + ↓ +Act + ↓ +Observe + ↓ +Evaluate + ↓ +Continue / Replan / Finish +``` + +代码模型: + +```ts +while (!goal.completed) { + const observation = await observe() + + const decision = await planner.decide(observation) + + const result = await executor.execute(decision) + + await evaluator.evaluate(result) +} +``` + +实际生产环境必须支持: + +```text +maxIterations +timeout +budget +cancel +approval +``` + +--- + +# 34. Agent Executor + +Agent Executor 不应该直接执行代码。 + +```text +Agent Executor + ↓ +Capability + ↓ +Action Runtime +``` + +例如: + +```ts +executor.execute({ + capability: "github.repository.create", + input: {...} +}) +``` + +最终: + +```text +Action Runtime +``` + +负责真正执行。 + +--- + +# 35. Agent Observation + +Action 完成后: + +```text +Execution Result + ↓ +Observation + ↓ +Agent +``` + +例如: + +```json +{ + "success": true, + "output": { + "pages": 1032, + "errors": 14 + } +} +``` + +Agent 决定: + +```text +继续 +``` + +或者: + +```text +重新规划 +``` + +--- + +# 36. Replanning + +Agent 不应该一次生成一个不可修改的巨大计划。 + +推荐: + +```text +Plan + ↓ +Execute 1-3 steps + ↓ +Observe + ↓ +Replan +``` + +尤其适用于: + +```text +外部 API +Web +SEO +DevOps +自动化 +``` + +因为环境会发生变化。 + +--- + +# 37. Agent Memory + +Memory 分为: + +```text +Short-term +Long-term +Working Context +``` + +--- + +## Short-term + +当前执行上下文: + +```text +最近 Action +最近结果 +当前计划 +``` + +--- + +## Long-term + +持久知识: + +```text +Project Preferences +Previous Decisions +Important Facts +``` + +--- + +## Working Context + +当前 Goal 所需的信息: + +```text +website +project +credentials +resources +previous results +``` + +--- + +# 38. Memory 不应该等于 Chat History + +不要: + +```text +整个聊天记录 + ↓ +每次全部发给 LLM +``` + +应该: + +```text +Memory Store + ↓ +Retrieve relevant context + ↓ +LLM +``` + +--- + +# 39. Agent Context + +统一: + +```ts +interface AgentContext { + goalId: string + + organizationId: string + + projectId?: string + + actor: Actor + + resources: ResourceRef[] + + capabilities: Capability[] + + memory: MemoryContext + + variables: Record + + budget?: AgentBudget +} +``` + +--- + +# 40. Agent Budget + +Agent 必须有预算控制。 + +```ts +interface AgentBudget { + maxTokens?: number + + maxIterations?: number + + maxExecutionTimeMs?: number + + maxTasks?: number + + maxMoney?: number + + maxCredits?: number +} +``` + +例如: + +```text +最多: +100 次 Action +20 次 LLM +$5 +30 分钟 +``` + +--- + +# 41. Agent Cost + +每个 Agent Execution 应记录: + +```text +LLM tokens +Tool calls +Action executions +External API calls +Money +Credits +``` + +最终: + +```text +Goal Cost +$2.37 +``` + +--- + +# 42. Approval + +Agent 遇到高风险 Action: + +```text +Agent + ↓ +Action + ↓ +requiresApproval + ↓ +Approval Task + ↓ +Human + ↓ +Approved + ↓ +Execution +``` + +例如: + +```text +删除服务器 +部署生产环境 +批量发送邮件 +批量发布内容 +批量外链 +``` + +--- + +# 43. Agent Safety Policy + +每个 Agent 都必须经过 Policy。 + +例如: + +```ts +interface AgentPolicy { + allowedCapabilities: string[] + + deniedCapabilities: string[] + + maxIterations: number + + requireApprovalFor: string[] +} +``` + +--- + +# 44. Agent Permission + +Agent 的权限不能自动等于用户全部权限。 + +例如: + +```text +User: +admin + +Agent: +seo-agent +``` + +Agent 可以被限制: + +```text +seo.website.* +seo.content.* +``` + +但: + +```text +server.delete +``` + +明确禁止。 + +--- + +# 45. Agent Identity + +Agent 应该拥有自己的 Actor: + +```text +actor.type = "agent" +actor.id = "agent_xxx" +``` + +Audit: + +```text +User + ↓ +Agent + ↓ +Action +``` + +因此能够知道: + +> “这个操作是谁授权的,又是哪个 Agent 执行的?” + +--- + +# 46. Agent Task + +Agent 创建: + +```text +Task +``` + +而不是: + +```text +AgentTask +``` + +避免出现两套系统。 + +正确: + +```text +Agent + ↓ +Task Runtime +``` + +--- + +# 47. Agent Workflow + +Agent 可以调用 Workflow: + +```text +Agent + ↓ +Workflow + ↓ +Tasks + ↓ +Actions +``` + +这非常适合: + +```text +稳定流程 +``` + +Agent 只负责: + +```text +选择 Workflow +填充参数 +观察结果 +``` + +--- + +# 48. Skill + Workflow + Agent + +三者关系: + +```text +Skill += +怎么解决问题 + +Workflow += +固定怎么执行 + +Agent += +当前应该怎么解决 +``` + +例如: + +```text +Skill: +SEO Audit + +Workflow: +标准 SEO Audit Workflow + +Agent: +根据网站情况决定是否使用完整 Workflow +``` + +--- + +# 49. Skill 可以推荐 Workflow + +Skill 可以声明: + +```json +{ + "recommendedWorkflows": [ + "seo.standard_audit" + ] +} +``` + +Agent 可以选择: + +```text +Workflow +``` + +或者: + +```text +动态 Action Plan +``` + +--- + +# 50. Agent Tool Calling + +模型产生: + +```json +{ + "capability": "github.repository.sync", + "input": { + "repositoryId": "repo_123" + } +} +``` + +Agent Runtime 不应该直接信任。 + +必须: + +```text +LLM Output + ↓ +Schema Validation + ↓ +Permission + ↓ +Scope + ↓ +Policy + ↓ +Approval + ↓ +Action Runtime +``` + +--- + +# 51. Tool Result + +Tool Result 必须标准化: + +```ts +interface ToolResult { + success: boolean + + data?: unknown + + error?: { + code: string + message: string + } + + executionId?: string + + taskId?: string +} +``` + +--- + +# 52. MCP Tool Result + +MCP 返回的结果最终应该转换为统一: + +```text +Capability Result +``` + +这样 Agent 不需要知道: + +```text +这是 MCP +这是 Plugin +这是 Core +``` + +它只知道: + +```text +Capability +``` + +--- + +# 53. Capability Adapter + +如果外部 MCP Tool 无法直接映射到 Action: + +```text +External MCP + ↓ +MCP Adapter + ↓ +Capability +``` + +Adapter 负责: + +```text +Input conversion +Output conversion +Error normalization +``` + +--- + +# 54. MCP Resource + +MCP Resource 可以映射: + +```text +DevOS Resource +``` + +例如: + +```text +github://repository/123 +``` + +对应: + +```text +github.repository:123 +``` + +Agent 可以读取: + +```text +Resource +``` + +再决定调用: + +```text +Action +``` + +--- + +# 55. Skill Discovery + +Agent 不应该搜索所有 Skill。 + +例如: + +```text +Goal: +部署 Next.js 应用 +``` + +搜索: + +```text +deploy +nextjs +application +``` + +返回: + +```text +application.deploy +docker.deploy +nextjs.deploy +``` + +然后再加载详细内容。 + +--- + +# 56. Capability Ranking + +搜索结果应该有: + +```text +relevance +permission +availability +quality +cost +``` + +例如: + +```text +server.deploy +score: 0.93 + +docker.deploy +score: 0.84 + +ssh.execute +score: 0.51 +``` + +优先选择高层 Capability。 + +--- + +# 57. 为什么不能让 Agent 直接 SSH + +例如: + +```text +Agent + ↓ +ssh.execute + ↓ +rm -rf / +``` + +风险非常高。 + +应该优先: + +```text +Agent + ↓ +server.deploy +``` + +高层 Action 可以拥有: + +```text +Schema +Permission +Policy +Validation +Audit +``` + +因此: + +> **Agent 应优先使用业务 Action,而不是低层原始工具。** + +--- + +# 58. Capability Abstraction Level + +建议: + +```text +Level 1 +Business Action + +Level 2 +System Action + +Level 3 +Raw Tool +``` + +例如: + +```text +deploy.application + ↓ +docker.run + ↓ +ssh.execute +``` + +Agent 默认优先 Level 1。 + +只有没有高层能力时,才允许向下。 + +--- + +# 59. Agent Fallback + +例如: + +```text +deploy.application +``` + +不存在。 + +Agent 可以发现: + +```text +docker.build +server.execute_command +``` + +然后组合: + +```text +docker.build + ↓ +server.execute_command +``` + +但如果存在高层: + +```text +deploy.application +``` + +就不应该自己拼底层 Action。 + +--- + +# 60. Agent Planning Policy + +Planner 可以设置: + +```text +prefer_existing_workflow +prefer_high_level_actions +minimize_tool_calls +minimize_cost +require_approval +``` + +例如: + +```json +{ + "preferHighLevelActions": true, + "minimizeToolCalls": true, + "maxIterations": 20 +} +``` + +--- + +# 61. Agent State Machine + +```text +pending + ↓ +planning + ↓ +executing + ↓ +observing + ↓ +evaluating + ├── completed + ├── replanning + ├── waiting + └── failed +``` + +取消: + +```text +任何状态 + ↓ +cancelled +``` + +--- + +# 62. Agent Run + +一次 Agent Goal 执行应该有: + +```ts +interface AgentRun { + id: string + + goalId: string + + status: AgentRunStatus + + model?: string + + provider?: string + + iterations: number + + tokenUsage?: TokenUsage + + cost?: ExecutionCost + + startedAt?: Date + + completedAt?: Date +} +``` + +--- + +# 63. Agent Step + +```ts +interface AgentStep { + id: string + + runId: string + + type: + | "thought" + | "plan" + | "tool_call" + | "observation" + | "evaluation" + | "approval" + + capabilityId?: string + + input?: unknown + + output?: unknown + + status: string + + createdAt: Date +} +``` + +注意: + +> 不要求把模型内部完整思维过程持久化或展示。 + +只保存: + +```text +decision summary +action +result +reason / metadata +``` + +--- + +# 64. Agent Trace + +UI: + +```text +Agent Run +──────────────────────────── + +Goal +10天完成 SEO Campaign + +Step 1 +✓ Website Scan + +Step 2 +✓ Keyword Research + +Step 3 +✓ Content Plan + +Step 4 +⏳ Generate Content + +Step 5 +○ Publish + +Step 6 +○ Backlinks +``` + +点击 Step: + +```text +Capability +Input +Execution +Output +Cost +Logs +``` + +--- + +# 65. Agent 与 Event + +Agent 可以订阅 Event: + +```text +deployment.completed +website.scan.completed +content.published +``` + +例如: + +```text +Event + ↓ +Agent Observation + ↓ +Agent Decision +``` + +--- + +# 66. Agent 与 Scheduler + +Scheduler 可以启动 Agent Goal: + +```text +每天 02:00 + ↓ +Create Agent Goal + ↓ +Agent Run +``` + +例如: + +```text +每天检查所有网站 SEO 健康状态。 +``` + +--- + +# 67. Agent 与 Webhook + +Webhook: + +```text +GitHub Push + ↓ +Event + ↓ +Agent Trigger + ↓ +Goal + ↓ +Plan +``` + +--- + +# 68. Agent Trigger + +统一: + +```ts +interface AgentTrigger { + type: + | "manual" + | "schedule" + | "event" + | "webhook" + + config: unknown + + goalTemplate: unknown +} +``` + +--- + +# 69. Agent 与 Plugin + +Plugin 提供: + +```text +Capability +Skill +MCP +``` + +Agent 自动发现。 + +因此 Plugin 安装: + +```text +Install SEO Plugin +``` + +之后 Agent 自动拥有: + +```text +SEO Skills +SEO Actions +SEO MCP +``` + +无需修改 Agent Core。 + +--- + +# 70. 这是 DevOS 的关键扩展机制 + +最终: + +```text +安装 Plugin + ↓ +Resources +Actions +Skills +MCP +UI + ↓ +Capability Registry + ↓ +Agent 自动发现 +``` + +因此: + +> **增加 Agent 能力,不需要修改 Agent。** + +只需要增加 Plugin。 + +--- + +# 71. AI SEO 示例 + +用户: + +```text +10天内给 a.com 做100篇软文 + 200个外链。 +``` + +Agent: + +```text +Goal + ↓ +Discover Skills + ↓ +seo.campaign.execute +``` + +Skill: + +```text +需要: +website +keyword data +content capability +backlink capability +``` + +Capability Discovery: + +```text +seo.website.scan +seo.keyword.research +seo.content.generate +seo.content.publish +seo.backlink.submit +``` + +--- + +# 72. Agent Plan + +```text +1. Scan website +2. Research keywords +3. Build content strategy +4. Generate 100 articles +5. Publish articles +6. Find backlink opportunities +7. Submit backlinks +8. Verify +9. Report +``` + +但是: + +> Agent 不一定一次性执行全部步骤。 + +可能: + +```text +Scan + ↓ +Observe + ↓ +Replan + ↓ +Keyword Research + ↓ +Observe + ↓ +Generate +``` + +--- + +# 73. 批量任务 + +100 篇文章不能: + +```text +Agent + ↓ +生成 100 × Tool Call +``` + +应该: + +```text +Agent + ↓ +Create Task + ↓ +Task creates Jobs + ↓ +100 Jobs + ↓ +Queue + ↓ +Workers +``` + +Agent 只负责: + +```text +规划 +``` + +而不是亲自执行 100 个工作单元。 + +--- + +# 74. Agent 与 Task 的边界 + +```text +Agent: +“What should we do?” + +Task: +“What work needs to be done?” + +Action: +“How do we execute it?” + +Execution: +“What actually happened?” +``` + +这是整个 AI Runtime 的核心分层。 + +--- + +# 75. Agent 不应该控制 Queue + +错误: + +```text +Agent + ↓ +Redis + ↓ +Queue +``` + +正确: + +```text +Agent + ↓ +Task Runtime + ↓ +Queue Runtime +``` + +--- + +# 76. Agent 不应该控制 Worker + +同样: + +```text +Agent + ↓ +Worker +``` + +禁止。 + +Agent 只: + +```text +Create Task +Execute Action +Observe Result +``` + +--- + +# 77. AI Runtime API + +建议: + +```text +POST /agents/goals +GET /agents/goals +GET /agents/goals/:id +POST /agents/goals/:id/cancel + +GET /agents/runs/:id +GET /agents/runs/:id/steps + +POST /capabilities/search +GET /capabilities/:id + +GET /skills +GET /skills/:id +``` + +--- + +# 78. Capability API + +```http +POST /api/capabilities/search +``` + +Request: + +```json +{ + "query": "deploy application", + "types": ["action", "skill", "workflow"], + "limit": 10 +} +``` + +Response: + +```json +{ + "items": [ + { + "id": "application.deploy", + "type": "action", + "name": "Deploy Application" + } + ] +} +``` + +--- + +# 79. Capability Detail API + +```http +GET /api/capabilities/application.deploy +``` + +返回: + +```text +Input Schema +Output Schema +Permissions +Description +Examples +Provider +Version +``` + +--- + +# 80. Skill API + +```http +GET /api/skills/seo.website.audit +``` + +返回: + +```text +Description +Inputs +Outputs +Required Capabilities +Instructions +Examples +``` + +--- + +# 81. MCP Gateway + +推荐: + +```text +packages/mcp/ +``` + +结构: + +```text +MCP Runtime +├── MCP Server +├── MCP Client +├── Tool Registry +├── Resource Registry +├── Prompt Registry +└── Adapter +``` + +--- + +# 82. Agent Runtime Package + +```text +packages/agent/ +├── runtime +├── planner +├── executor +├── observer +├── evaluator +├── memory +├── policy +└── budget +``` + +--- + +# 83. Skill Runtime + +```text +packages/skill/ +├── registry +├── loader +├── resolver +├── validator +└── runtime +``` + +--- + +# 84. Capability Runtime + +```text +packages/capability/ +├── registry +├── discovery +├── resolver +├── ranking +├── permission-filter +└── adapters +``` + +--- + +# 85. 模型 Provider + +Agent Runtime 不应该绑定单一 LLM。 + +统一: + +```ts +interface ModelProvider { + generate(request: ModelRequest): Promise + + stream(request: ModelRequest): AsyncIterable +} +``` + +支持: + +```text +OpenAI +Anthropic +Google +Local +OpenRouter +Custom +``` + +--- + +# 86. Model Registry + +```text +Model Registry +``` + +记录: + +```text +Provider +Model +Context Window +Pricing +Capabilities +Vision +Tool Calling +Structured Output +``` + +Agent 可以选择: + +```text +cheap model +fast model +reasoning model +vision model +``` + +--- + +# 87. Model Policy + +不同任务可以选择不同模型: + +```text +简单分类 +→ Fast / Cheap + +复杂 Planning +→ Reasoning + +图片分析 +→ Vision +``` + +不要把模型选择硬编码进 Agent。 + +--- + +# 88. Structured Output + +Planner 必须尽量使用: + +```text +JSON Schema +``` + +例如: + +```ts +const planSchema = z.object({ + steps: z.array(...) +}) +``` + +避免: + +```text +LLM + ↓ +纯文本 + ↓ +正则解析 +``` + +--- + +# 89. Agent Error Handling + +Agent 可能遇到: + +```text +Capability unavailable +Permission denied +Tool failed +Invalid input +Timeout +Budget exceeded +Model error +``` + +统一处理: + +```text +Retry +Fallback +Replan +Ask Human +Fail +``` + +--- + +# 90. Human-in-the-loop + +Agent 不应该永远自动完成。 + +可以: + +```text +Agent + ↓ +Need decision + ↓ +Human Approval + ↓ +Continue +``` + +Task: + +```text +waiting +``` + +Approval 完成: + +```text +running +``` + +--- + +# 91. Agent Chat + +聊天只是 Agent 的一个入口。 + +```text +Chat + ↓ +Agent Goal +``` + +而不是: + +```text +Chatbot += +Agent Runtime +``` + +未来还可以: + +```text +API +CLI +Scheduler +Webhook +MCP +``` + +创建 Goal。 + +--- + +# 92. Agent UI + +推荐: + +```text +Agents +├── Agents +├── Goals +├── Runs +├── Skills +├── Capabilities +└── Models +``` + +Agent Detail: + +```text +Agent +──────────────── + +Capabilities +Skills +Policies +Models +Memory +Runs +Cost +``` + +--- + +# 93. Agent Run UI + +```text +Goal +│ +├── Planning ✓ +│ +├── Website Scan ✓ +│ +├── Keyword Research ✓ +│ +├── Generate Content ⏳ +│ +└── Publish ○ +``` + +每一步都能进入: + +```text +Task +Execution +Logs +Output +``` + +--- + +# 94. Agent Debug Mode + +开发环境必须支持: + +```text +Agent Trace +Capability Discovery +Selected Skill +Plan +Tool Calls +Execution IDs +Task IDs +Cost +Errors +``` + +这样开发者才能调试 Agent。 + +--- + +# 95. 不要实现“万能 Agent” + +第一版不要: + +```text +One giant agent +``` + +推荐: + +```text +Agent Runtime ++ +Agent Profiles +``` + +例如: + +```text +General Agent +SEO Agent +DevOps Agent +Content Agent +``` + +它们共用 Runtime。 + +--- + +# 96. Agent Profile + +```ts +interface AgentProfile { + id: string + + name: string + + description?: string + + systemInstructions?: string + + allowedSkills?: string[] + + allowedCapabilities?: string[] + + deniedCapabilities?: string[] + + modelPolicy?: ModelPolicy + + budget?: AgentBudget + + policy?: AgentPolicy +} +``` + +--- + +# 97. SEO Agent + +```text +SEO Agent +│ +├── Skills +│ ├── seo.audit +│ ├── seo.content +│ └── seo.backlink +│ +├── Capabilities +│ └── seo.* +│ +└── Policy +``` + +它不需要独立 Runtime。 + +--- + +# 98. DevOps Agent + +```text +DevOps Agent +│ +├── server.* +├── docker.* +├── deployment.* +└── monitoring.* +``` + +依旧使用: + +```text +Agent Runtime +``` + +--- + +# 99. 最终完整链路 + +```text + User + │ + ▼ + Goal + │ + ▼ + Agent Runtime + │ + ┌───────┴───────┐ + ▼ ▼ + Skill Capability Search + │ │ + └───────┬───────┘ + ▼ + Plan + │ + ▼ + Task + │ + ▼ + Job + │ + ▼ + Action + │ + ▼ + Action Runtime + │ + ▼ + Execution + │ + ▼ + Event + │ + ▼ + Observation + │ + ▼ + Agent + │ + ┌───────┼────────┐ + ▼ ▼ ▼ + Continue Replan Complete +``` + +--- + +# 100. MCP 的完整位置 + +```text + Agent + │ + ▼ + Capability Layer + │ + ┌────────┼─────────┐ + ▼ ▼ ▼ + Action Skill MCP + │ │ + │ ▼ + │ External System + │ + ▼ + Action Runtime +``` + +MCP 是能力来源 / 适配层,不是 DevOS 的第二套业务执行系统。 + +--- + +# 101. Plugin 的完整位置 + +```text +Plugin +│ +├── Resource +├── Action +├── Skill +├── MCP +├── Workflow +└── UI + │ + ▼ +Capability Registry + │ + ▼ +Agent +``` + +所以: + +> **Plugin 是能力供应商,Agent 是能力消费者。** + +--- + +# 102. 黄金规则 + +### Rule 1 + +```text +Agent 不直接操作数据库 +``` + +### Rule 2 + +```text +Agent 不直接操作 Queue +``` + +### Rule 3 + +```text +Agent 不直接操作 Worker +``` + +### Rule 4 + +```text +Agent 必须通过 Capability / Action 执行 +``` + +### Rule 5 + +```text +Skill 不直接执行底层业务 +``` + +### Rule 6 + +```text +MCP 不绕过 Action Runtime +``` + +### Rule 7 + +```text +Agent Task 必须使用 DevOS Task Runtime +``` + +### Rule 8 + +```text +Agent 必须经过 Permission / Policy +``` + +### Rule 9 + +```text +Agent Capability Discovery 必须进行权限过滤 +``` + +### Rule 10 + +```text +不要一次向 LLM 暴露全部 Tools +``` + +### Rule 11 + +```text +优先高层 Business Action +``` + +### Rule 12 + +```text +Agent Runtime 不绑定具体模型 +``` + +--- + +# 103. Zcode 实现要求 + +新增: + +```text +packages/ +├── capability/ +├── skill/ +├── agent/ +└── mcp/ +``` + +核心模块: + +```text +CapabilityRegistry +CapabilityDiscovery +CapabilityResolver +CapabilityRanker + +SkillRegistry +SkillLoader +SkillResolver + +AgentRuntime +AgentPlanner +AgentExecutor +AgentObserver +AgentEvaluator +AgentMemory +AgentPolicy +AgentBudget + +MCPServer +MCPClient +MCPToolRegistry +MCPAdapter + +ModelRegistry +ModelProvider +``` + +--- + +# 104. 第一阶段验收 Demo + +Zcode 必须完成以下完整演示。 + +## Demo 1:Capability Discovery + +输入: + +```text +deploy application +``` + +返回: + +```text +application.deploy +docker.build +server.health_check +``` + +--- + +## Demo 2:Skill Discovery + +输入: + +```text +SEO audit +``` + +返回: + +```text +seo.website.audit +``` + +--- + +## Demo 3:Agent Goal + +输入: + +```text +检查 example.com 的 SEO +``` + +完整链路: + +```text +Goal + ↓ +Agent + ↓ +Skill + ↓ +Capability Discovery + ↓ +seo.website.scan + ↓ +Task + ↓ +Execution + ↓ +Result + ↓ +Agent + ↓ +Report +``` + +--- + +## Demo 4:MCP + +外部 MCP Tool: + +```text +seo_scan_website +``` + +最终: + +```text +MCP + ↓ +seo.website.scan + ↓ +Action Runtime +``` + +--- + +## Demo 5:Plugin → Agent + +安装: + +```text +GitHub Plugin +``` + +之后: + +```text +Capability Registry +``` + +自动出现: + +```text +github.repository.* +``` + +Agent 可以立即发现这些能力。 + +**不允许修改 Agent Runtime 源码。** + +--- + +# 105. 最终目标 + +完成 `06` 后,DevOS 的核心已经形成: + +```text + ┌───────────────┐ + │ Agent │ + └───────┬───────┘ + │ + Skill / Plan + │ + ▼ + Capability Registry + │ + ┌─────────────┼─────────────┐ + ▼ ▼ ▼ + Action MCP Workflow + │ │ │ + └─────────────┼─────────────┘ + ▼ + Action Runtime + │ + ▼ + Task + │ + ▼ + Job + │ + ▼ + Queue + │ + ▼ + Worker + │ + ▼ + Execution + │ + ▼ + Event + │ + ▼ + Observation + │ + └──────→ Agent +``` + +这一步完成后,DevOS 就不再只是一个“后台框架”。 + +它实际上开始形成: + +> **Resource Runtime + Action Runtime + Plugin Runtime + Execution Runtime + Capability Runtime + Agent Runtime** + +这几个 Runtime 共同构成你后面真正可以反复复用的 **DevOS Application/Agent Platform Core**。 diff --git a/Docs/DevOS-Platform-v2/07_UI_SHELL_APP_MODULE.md b/Docs/DevOS-Platform-v2/07_UI_SHELL_APP_MODULE.md new file mode 100644 index 0000000..893854e --- /dev/null +++ b/Docs/DevOS-Platform-v2/07_UI_SHELL_APP_MODULE.md @@ -0,0 +1,3654 @@ +# `07_UI_SHELL_APP_MODULE.md` + +# DevOS Developer Work OS +## UI Shell / App / Module / Plugin Runtime 设计规范 + +Version: 1.0 + +--- + +# 1. 文档目标 + +本文定义 DevOS 前端 UI 平台架构。 + +目标不是开发一个固定的 Admin Dashboard,而是建立一个: + +> 可复用、可扩展、可插拔、可被 App/Plugin/MCP/Agent 动态扩展的前端 UI Shell。 + +DevOS 前端应该能够支持: + +- Core 页面 +- App 页面 +- Module 页面 +- Plugin 页面 +- Resource 页面 +- Action 页面 +- Settings 页面 +- Dashboard Widget +- Statistics Widget +- Chat Widget +- Report Widget +- Context Action +- Command Palette +- Global Search +- Workspace +- Agent UI + +最终结构: + +```text +DevOS UI Shell +│ +├── Core UI +│ ├── Layout +│ ├── Navigation +│ ├── Header +│ ├── Sidebar +│ ├── Workspace +│ ├── Command Palette +│ ├── Global Search +│ ├── Notifications +│ └── User Menu +│ +├── App Runtime +│ ├── App Registry +│ ├── Module Registry +│ ├── Route Registry +│ ├── Navigation Registry +│ └── Widget Registry +│ +├── Resource UI +│ ├── List +│ ├── Detail +│ ├── Create +│ ├── Edit +│ └── Actions +│ +├── Plugin UI +│ ├── Pages +│ ├── Settings +│ ├── Dashboard +│ ├── Statistics +│ ├── Reports +│ ├── Chat +│ └── Context Actions +│ +└── Agent UI + ├── Goals + ├── Runs + ├── Tasks + ├── Execution Trace + └── Agent Chat +```` + +--- + +# 2. 核心原则 + +DevOS UI 必须遵循: + +```text +UI + ↓ +UI Action / Query + ↓ +API + ↓ +Action Runtime / Resource Runtime + ↓ +Backend +``` + +禁止: + +```text +UI + ↓ +直接操作数据库 +``` + +禁止: + +```text +UI + ↓ +自己实现业务逻辑 +``` + +禁止: + +```text +Plugin UI + ↓ +绕过 DevOS Runtime +``` + +前端负责: + +* 展示 +* 用户交互 +* 表单 +* 状态 +* 路由 +* 权限可见性 +* 调用 API +* 展示执行结果 + +后端负责: + +* Authentication +* Authorization +* Business Logic +* Action Runtime +* Resource Runtime +* Task +* Job +* Queue +* Audit +* Transaction + +--- + +# 3. App / Module / Plugin 的区别 + +必须明确三者边界。 + +## 3.1 App + +App 是一个完整的产品/业务应用。 + +例如: + +```text +DevOS +SEO App +DevOps App +CRM App +Content App +``` + +App 可以包含: + +```text +Pages +Resources +Actions +Skills +Plugins +Widgets +Settings +Agents +``` + +例如: + +```text +SEO App +├── Websites +├── Keywords +├── Content +├── Backlinks +├── Reports +└── SEO Agent +``` + +--- + +# 4. Module + +Module 是 App 内部的功能模块。 + +例如: + +```text +SEO App +├── Website Module +├── Keyword Module +├── Content Module +├── Backlink Module +└── Report Module +``` + +Module 通常不应该成为独立安装包。 + +它主要解决: + +> 如何组织大型 App。 + +--- + +# 5. Plugin + +Plugin 是可独立安装/卸载/启用/禁用的扩展。 + +例如: + +```text +GitHub Plugin +Browser Plugin +Cloudflare Plugin +Google Search Console Plugin +OpenAI Plugin +``` + +Plugin 可以提供: + +```text +Resource +Action +Skill +MCP +Workflow +Page +Settings +Widget +Context Action +``` + +例如: + +```text +GitHub Plugin +├── Resource +│ ├── repository +│ ├── issue +│ └── pull_request +│ +├── Action +│ ├── repository.clone +│ ├── repository.create +│ └── issue.create +│ +├── Skill +│ └── github.code_review +│ +├── MCP +│ └── github +│ +└── UI + ├── Repositories + ├── Settings + └── Statistics +``` + +--- + +# 6. UI Shell + +DevOS Shell 是所有 App/Plugin 共用的 UI 基础。 + +推荐: + +```text +React +TypeScript +React Router +Ant Design +TanStack Query +Zustand +TipTap +``` + +Shell: + +```text +┌───────────────────────────────────────────────┐ +│ Header │ +│ Logo | Search | Command | Notifications | Me │ +├──────────────┬────────────────────────────────┤ +│ │ │ +│ Navigation │ Workspace │ +│ │ │ +│ Dashboard │ Breadcrumb │ +│ Apps │ │ +│ Resources │ Page │ +│ Plugins │ │ +│ Settings │ │ +│ │ │ +│ │ │ +└──────────────┴────────────────────────────────┘ +``` + +--- + +# 7. App Registry + +所有 App 都必须通过 Registry 注册。 + +```ts +export interface AppManifest { + id: string; + name: string; + description?: string; + + version: string; + + icon?: string; + + route?: string; + + navigation?: NavigationItem[]; + + modules?: ModuleManifest[]; + + widgets?: WidgetManifest[]; + + permissions?: string[]; + + metadata?: Record; +} +``` + +例如: + +```ts +{ + id: "seo", + name: "SEO", + version: "1.0.0", + route: "/seo" +} +``` + +--- + +# 8. Module Manifest + +```ts +export interface ModuleManifest { + id: string; + + appId: string; + + name: string; + + version: string; + + routes?: RouteDefinition[]; + + navigation?: NavigationItem[]; + + widgets?: WidgetManifest[]; + + resources?: string[]; + + permissions?: string[]; +} +``` + +例如: + +```text +seo.website +seo.keyword +seo.content +seo.backlink +``` + +--- + +# 9. Plugin UI Manifest + +Plugin UI 必须与 Plugin Manifest 统一。 + +```ts +export interface PluginUIManifest { + pluginId: string; + + routes?: RouteDefinition[]; + + navigation?: NavigationItem[]; + + widgets?: WidgetManifest[]; + + settings?: SettingsPageDefinition[]; + + contextActions?: ContextActionDefinition[]; +} +``` + +--- + +# 10. Route Registry + +不要让每个 Plugin 自己修改 React Router。 + +统一: + +```text +Route Registry + ↓ +React Router +``` + +定义: + +```ts +export interface RouteDefinition { + id: string; + + path: string; + + title: string; + + component: string; + + icon?: string; + + permission?: string; + + children?: RouteDefinition[]; + + metadata?: Record; +} +``` + +例如: + +```ts +{ + id: "github.repositories", + path: "/plugins/github/repositories", + title: "Repositories", + component: "github.repositories" +} +``` + +--- + +# 11. Route Namespace + +Plugin 路由必须隔离。 + +推荐: + +```text +/plugins/{pluginId}/... +``` + +例如: + +```text +/plugins/github/repositories +/plugins/github/issues + +/plugins/cloudflare/zones +/plugins/cloudflare/dns + +/plugins/browser/sessions +``` + +App: + +```text +/seo/... +/devops/... +/crm/... +``` + +Core: + +```text +/dashboard +/tasks +/agents +/settings +/plugins +``` + +禁止 Plugin 任意覆盖: + +```text +/settings +/users +/tasks +``` + +除非明确声明扩展点。 + +--- + +# 12. Navigation Registry + +Navigation 不应该硬编码。 + +统一: + +```ts +NavigationRegistry.register(...) +``` + +结构: + +```ts +export interface NavigationItem { + id: string; + + title: string; + + path?: string; + + icon?: string; + + parentId?: string; + + order?: number; + + permission?: string; + + visible?: boolean; + + badge?: BadgeDefinition; + + metadata?: Record; +} +``` + +例如: + +```text +SEO +├── Overview +├── Websites +├── Keywords +├── Content +└── Backlinks +``` + +Plugin 安装后: + +```text +Plugins +├── GitHub +│ ├── Repositories +│ └── Issues +│ +├── Cloudflare +│ └── Zones +│ +└── Browser + └── Sessions +``` + +--- + +# 13. Navigation 权限 + +前端可以根据权限隐藏菜单。 + +例如: + +```ts +permission: "seo.website.read" +``` + +没有权限: + +```text +Navigation → hidden +``` + +但是: + +> 前端隐藏不是安全机制。 + +用户直接访问: + +```text +/seo/websites +``` + +后端仍必须检查: + +```text +seo.website.read +``` + +真正的安全边界始终是 Backend Authorization。 + +--- + +# 14. Dynamic Navigation + +Plugin 启用后: + +```text +Plugin Runtime + ↓ +Plugin Manifest + ↓ +Navigation Registry + ↓ +UI Shell + ↓ +Navigation 更新 +``` + +不应该修改: + +```text +Sidebar.tsx +``` + +来添加 Plugin。 + +--- + +# 15. Resource UI + +Resource Metadata 应该能够驱动通用 UI。 + +例如: + +```text +Resource: + +seo.website +``` + +定义: + +```ts +{ + id: "seo.website", + + fields: { + name: {...}, + domain: {...}, + status: {...} + }, + + actions: [ + "seo.website.create", + "seo.website.update", + "seo.website.delete", + "seo.website.scan" + ] +} +``` + +UI 可以自动生成: + +```text +Website List +Website Detail +Create Website +Edit Website +``` + +--- + +# 16. Resource List + +通用 Resource List: + +```text +┌─────────────────────────────────────────────┐ +│ Websites + Create │ +├─────────────────────────────────────────────┤ +│ Search │ +│ │ +│ Domain Status Last Scan │ +│ example.com Healthy 2 min ago │ +│ example.org Warning 1 hour ago │ +│ │ +└─────────────────────────────────────────────┘ +``` + +表格定义可以来自: + +```ts +ResourceMetadata +``` + +但允许业务页面覆盖默认 UI。 + +--- + +# 17. Resource Detail + +```text +/seo/websites/:id +``` + +Detail 页面: + +```text +Website +├── Overview +├── SEO +├── Keywords +├── Content +├── Backlinks +├── Tasks +├── Executions +└── Activity +``` + +其中: + +```text +Overview +``` + +可以是通用 Resource UI。 + +而: + +```text +SEO +Keywords +Backlinks +``` + +可以是 App 自定义页面。 + +--- + +# 18. Action UI + +Action 不是简单的 Button。 + +Action Metadata: + +```ts +export interface ActionUIConfig { + actionId: string; + + label: string; + + icon?: string; + + confirm?: boolean; + + danger?: boolean; + + form?: FormSchema; + + resultView?: ResultViewDefinition; +} +``` + +例如: + +```text +Website Detail + +[Scan Website] +``` + +点击: + +```text +seo.website.scan +``` + +进入: + +```text +Action Runtime +``` + +而不是: + +```text +POST /scan +``` + +再由 Controller 自己实现业务逻辑。 + +--- + +# 19. Action 状态 + +对于异步 Action: + +```text +pending +running +completed +failed +cancelled +``` + +UI 应该统一展示: + +```text +ActionExecution +``` + +例如: + +```text +Scan Website + +Running... + +████████████░░░░░░ 65% + +Current: +Checking backlinks +``` + +--- + +# 20. Task UI + +Action 如果创建 Task: + +```text +Action + ↓ +Task + ↓ +Job + ↓ +Execution +``` + +UI: + +```text +Task +├── Status +├── Progress +├── Jobs +├── Logs +├── Executions +└── Output +``` + +Agent、用户、Plugin 都应该使用同一 Task UI。 + +--- + +# 21. Agent UI + +Agent 页面: + +```text +/agents +``` + +列表: + +```text +SEO Agent +DevOps Agent +General Agent +Content Agent +``` + +Agent Detail: + +```text +Agent +├── Overview +├── Goals +├── Runs +├── Skills +├── Capabilities +├── Policies +└── Settings +``` + +--- + +# 22. Agent Chat + +Chat 只是 Agent 的一种 UI。 + +例如: + +```text +┌─────────────────────────────────────────────┐ +│ SEO Agent │ +├─────────────────────────────────────────────┤ +│ │ +│ User: │ +│ 检查 example.com 的 SEO │ +│ │ +│ Agent: │ +│ 我发现该网站存在 12 个问题。 │ +│ │ +│ [View Report] [Create Tasks] │ +│ │ +└─────────────────────────────────────────────┘ +``` + +Chat 不应该直接执行业务。 + +流程: + +```text +Chat + ↓ +Agent Goal + ↓ +Agent Runtime + ↓ +Capability + ↓ +Action Runtime +``` + +--- + +# 23. Widget Registry + +Widget 是 DevOS UI 的重要扩展机制。 + +Plugin 可以提供: + +```text +Dashboard Widget +Statistics Widget +Report Widget +Chat Widget +Resource Widget +Agent Widget +``` + +定义: + +```ts +export interface WidgetManifest { + id: string; + + title: string; + + type: + | "dashboard" + | "statistics" + | "report" + | "chat" + | "resource" + | "agent"; + + component: string; + + size?: "small" | "medium" | "large"; + + permissions?: string[]; + + dataSource?: string; + + metadata?: Record; +} +``` + +--- + +# 24. Dashboard Extension + +Dashboard 不应该写死。 + +例如: + +```text +Dashboard +├── System Health +├── Tasks +├── Agent Activity +│ +├── SEO Traffic +├── SEO Issues +│ +├── GitHub PRs +└── Cloudflare Traffic +``` + +其中: + +```text +SEO Traffic +``` + +来自 SEO App。 + +```text +GitHub PRs +``` + +来自 GitHub Plugin。 + +--- + +# 25. Widget Slot + +Shell 提供 Extension Point: + +```text +dashboard.main +dashboard.sidebar + +resource.detail.before +resource.detail.after + +resource.list.toolbar +resource.detail.toolbar + +agent.sidebar +agent.chat.toolbar +``` + +Plugin 可以: + +```ts +WidgetRegistry.register({ + slot: "dashboard.main", + widget: "github.pull_requests" +}); +``` + +这样 Plugin 不需要修改 Core Dashboard。 + +--- + +# 26. Context Action + +Context Action 是 Plugin 非常重要的 UI 能力。 + +例如: + +```text +用户查看: + +Website: example.com +``` + +右上角: + +```text +More +├── Scan SEO +├── Open in Browser +├── Search Google +├── Create Content +└── Ask Agent +``` + +定义: + +```ts +export interface ContextActionDefinition { + id: string; + + label: string; + + icon?: string; + + resourceTypes?: string[]; + + actionId: string; + + permission?: string; +} +``` + +例如: + +```ts +{ + id: "browser.open_website", + resourceTypes: ["seo.website"], + actionId: "browser.open_url" +} +``` + +--- + +# 27. Resource Context Action + +对于: + +```text +seo.website +``` + +Plugin 可以注册: + +```text +Open Browser +Run SEO Scan +Search Backlinks +Create Article +Ask SEO Agent +``` + +所有这些最终必须转换为: + +```text +Action +``` + +或者: + +```text +Agent Goal +``` + +--- + +# 28. Settings UI + +Settings 必须支持: + +```text +Core Settings +App Settings +Plugin Settings +User Settings +Organization Settings +Project Settings +``` + +结构: + +```text +Settings +├── General +├── Account +├── Organization +├── Security +├── Agents +├── Models +├── Plugins +│ ├── GitHub +│ ├── Cloudflare +│ └── Browser +└── Developer +``` + +--- + +# 29. Plugin Settings + +Plugin 自己可以定义 Settings Page: + +```ts +export interface SettingsPageDefinition { + id: string; + + pluginId: string; + + title: string; + + path: string; + + component: string; + + permissions?: string[]; +} +``` + +例如: + +```text +/settings/plugins/github +``` + +页面: + +```text +GitHub + +Connection +[ Connected ] + +Default Organization +[ example ] + +Webhook +[ Enabled ] + +[ Save ] +``` + +保存: + +```text +UI + ↓ +Action + ↓ +Action Runtime +``` + +--- + +# 30. Settings 不应该直接调用 Plugin API + +禁止: + +```ts +fetch("https://api.github.com/...") +``` + +在 React Component 中直接执行。 + +应该: + +```text +GitHub Settings UI + ↓ +github.connection.update + ↓ +Action Runtime + ↓ +GitHub Plugin +``` + +这样才能统一: + +* Permission +* Audit +* Validation +* Retry +* Error +* Secret +* Logging + +--- + +# 31. Secret UI + +Plugin 可能需要: + +```text +API Key +Token +OAuth +Secret +``` + +UI 只能操作: + +```text +Secret Reference +``` + +不要让普通 UI State 长期保存明文 Secret。 + +例如: + +```ts +{ + credentialId: "cred_xxx" +} +``` + +后端负责: + +```text +Credential Store +``` + +--- + +# 32. Global Search + +DevOS 应提供统一搜索。 + +搜索范围: + +```text +Resources +Tasks +Agents +Plugins +Actions +Users +Projects +Documentation +``` + +例如: + +```text +Search: example.com +``` + +结果: + +```text +Websites + example.com + +Tasks + SEO Scan example.com + +Reports + SEO Audit example.com + +Agent Runs + SEO Agent / example.com +``` + +--- + +# 33. Search Provider + +不要让 Search UI 知道具体数据库。 + +统一: + +```ts +export interface SearchProvider { + search( + query: SearchQuery + ): Promise; +} +``` + +Backend 根据: + +```text +Resource Registry +Plugin Registry +Search Index +``` + +返回结果。 + +--- + +# 34. Command Palette + +DevOS 应提供: + +```text +Cmd/Ctrl + K +``` + +Command Palette。 + +例如: + +```text +> scan example.com + +Actions + Scan Website + +Pages + Website + +Agents + Ask SEO Agent +``` + +Command Palette 可以搜索: + +```text +Navigation +Resources +Actions +Commands +Agents +``` + +--- + +# 35. Command Registry + +```ts +export interface CommandDefinition { + id: string; + + title: string; + + description?: string; + + keywords?: string[]; + + actionId?: string; + + route?: string; + + permission?: string; +} +``` + +Plugin 可以注册 Command。 + +例如: + +```text +GitHub: + Create Repository + Open Pull Requests +``` + +--- + +# 36. Breadcrumb + +Breadcrumb 不应该硬编码。 + +由 Route / Resource Context 自动生成。 + +例如: + +```text +SEO +/ +Websites +/ +example.com +``` + +如果进入: + +```text +SEO +/ +Websites +/ +example.com +/ +Scan +``` + +Action 页面可以显示: + +```text +SEO / Websites / example.com / Scan +``` + +--- + +# 37. Workspace + +DevOS 应支持 Workspace 概念。 + +Workspace 可以理解为: + +> 用户当前工作的上下文空间。 + +例如: + +```text +Workspace +├── Project +├── Organization +├── Environment +└── Active Resources +``` + +Header: + +```text +[ Organization ▼ ] +[ Project ▼ ] +``` + +切换 Workspace 后: + +```text +Navigation +Data +Permissions +Agents +Tasks +``` + +都应该根据 Workspace Context 更新。 + +--- + +# 38. Workspace Context + +前端: + +```ts +interface WorkspaceContext { + organizationId?: string; + + projectId?: string; + + environmentId?: string; +} +``` + +所有 API Query 都应该带: + +```text +organizationId +projectId +``` + +但是: + +> 前端传入的 Workspace Context 不能作为安全依据。 + +Backend 必须重新验证: + +```text +Actor ++ +Organization ++ +Project ++ +Resource Scope +``` + +--- + +# 39. React Query + +Server State 统一使用: + +```text +TanStack Query +``` + +例如: + +```ts +useQuery({ + queryKey: [ + "resource", + "seo.website", + websiteId + ], + queryFn: ... +}); +``` + +禁止使用 Zustand 保存大量 Server State。 + +--- + +# 40. Zustand + +Zustand 用于: + +```text +UI State +Session UI +Sidebar State +Workspace UI +Command Palette +Modal +Theme +Preferences +``` + +不要: + +```text +Zustand + ↓ +保存整个后端数据库 +``` + +--- + +# 41. Form + +通用 Resource Form 可以根据 Schema 自动生成。 + +例如: + +```ts +{ + fields: { + name: { + type: "string", + required: true + }, + + domain: { + type: "url", + required: true + } + } +} +``` + +生成: + +```text +Name +[________________] + +Domain +[________________] + +[ Save ] +``` + +但复杂业务表单允许完全自定义 React Component。 + +--- + +# 42. Dynamic UI 与 Custom UI + +DevOS 不应该追求: + +> 所有页面都自动生成。 + +正确原则: + +```text +简单 CRUD + ↓ +Schema-driven UI + +复杂业务 + ↓ +Custom React UI +``` + +例如: + +```text +User CRUD +→ Dynamic UI + +SEO Website +→ Custom UI + Resource metadata + +Agent Workspace +→ Custom UI + +DevOps Terminal +→ Custom UI +``` + +--- + +# 43. UI Registry + +统一 UI Registry: + +```text +AppRegistry +ModuleRegistry +PluginRegistry +RouteRegistry +NavigationRegistry +WidgetRegistry +CommandRegistry +ContextActionRegistry +``` + +建议: + +```ts +export interface UIRegistry { + apps: AppRegistry; + + modules: ModuleRegistry; + + routes: RouteRegistry; + + navigation: NavigationRegistry; + + widgets: WidgetRegistry; + + commands: CommandRegistry; + + contextActions: ContextActionRegistry; +} +``` + +--- + +# 44. Registry 生命周期 + +系统启动: + +```text +Load Core + ↓ +Load Apps + ↓ +Load Modules + ↓ +Load Plugins + ↓ +Register Routes + ↓ +Register Navigation + ↓ +Register Widgets + ↓ +Register Commands + ↓ +Register Context Actions + ↓ +Render Shell +``` + +Plugin 动态启用: + +```text +Plugin Enable + ↓ +Load Manifest + ↓ +Register UI + ↓ +Invalidate Registry + ↓ +Shell Update +``` + +Plugin 禁用: + +```text +Plugin Disable + ↓ +Unregister UI + ↓ +Invalidate Registry + ↓ +Routes disappear + ↓ +Navigation disappears + ↓ +Widgets disappear +``` + +--- + +# 45. Lazy Loading + +Plugin 页面必须支持 Lazy Loading。 + +不要: + +```text +App Startup + ↓ +加载所有 Plugin UI +``` + +应该: + +```text +Shell + ↓ +Load Manifest + ↓ +User opens Plugin page + ↓ +Lazy Load Component +``` + +例如: + +```ts +const GitHubRepositories = + lazy(() => + import("@devos/plugin-github/ui/repositories") + ); +``` + +--- + +# 46. Plugin UI Isolation + +Plugin UI 必须: + +* 使用自己的 namespace +* 不能覆盖 Core Route +* 不能随意修改全局 State +* 不能直接访问数据库 +* 不能绕过 Permission +* 不能绕过 Action Runtime + +Plugin 可以通过: + +```text +Registry +Extension Point +Action +Resource +Event +``` + +与 Core 集成。 + +--- + +# 47. Error Boundary + +每个 App/Plugin UI 都必须有 Error Boundary。 + +例如: + +```text +Shell +├── Core Error Boundary +│ +├── SEO Error Boundary +│ +├── GitHub Plugin Error Boundary +│ +└── Browser Plugin Error Boundary +``` + +如果 GitHub Plugin 崩溃: + +```text +GitHub Plugin failed +``` + +不能导致: + +```text +整个 DevOS 白屏 +``` + +--- + +# 48. Permission Guard + +前端: + +```tsx + + + +``` + +作用: + +```text +UI visibility +``` + +不是: + +```text +Security +``` + +Backend 必须再次验证。 + +--- + +# 49. Feature Flag + +UI 支持 Feature Flag: + +```ts +feature("new_agent_ui") +``` + +可以控制: + +```text +App +Module +Plugin +Widget +Route +``` + +例如: + +```text +agent.workspace.v2 +``` + +--- + +# 50. UI Extension API + +建议提供: + +```ts +ui.registerRoute(...) + +ui.registerNavigation(...) + +ui.registerWidget(...) + +ui.registerCommand(...) + +ui.registerContextAction(...) + +ui.registerSettings(...) + +ui.registerSlotExtension(...) +``` + +Plugin 开发者不需要修改: + +```text +Core UI source +``` + +--- + +# 51. 示例:GitHub Plugin + +安装: + +```text +GitHub Plugin +``` + +Plugin Runtime 注册: + +```text +Resources: +github.repository +github.issue +github.pull_request + +Actions: +github.repository.create +github.repository.clone +github.issue.create +github.pull_request.merge + +Skills: +github.code_review + +MCP: +github + +UI: +Repositories +Issues +Pull Requests +Settings +Statistics +``` + +UI 自动出现: + +```text +Plugins +└── GitHub + ├── Repositories + ├── Issues + ├── Pull Requests + ├── Statistics + └── Settings +``` + +同时 Dashboard: + +```text +GitHub PR Widget +``` + +Command Palette: + +```text +Create GitHub Repository +``` + +Context Action: + +```text +Resource: github.repository + +Open +Clone +Create Issue +Ask Agent +``` + +--- + +# 52. 示例:Browser Plugin + +Browser Plugin: + +```text +Resource: +browser.session + +Actions: +browser.open +browser.navigate +browser.screenshot + +MCP: +browser + +Skill: +browser.research + +UI: +Browser Sessions +Browser Console +Browser Settings +``` + +SEO Website 页面: + +```text +example.com +``` + +Context Actions: + +```text +Open Browser +Screenshot +Run SEO Audit +Ask Agent +``` + +其中: + +```text +Open Browser + ↓ +browser.open + ↓ +Action Runtime +``` + +--- + +# 53. 示例:SEO App + +SEO App 不应该重新实现: + +```text +Layout +Navigation +Task UI +Agent UI +Settings +Notification +Permission +Search +Command Palette +``` + +这些全部由 DevOS Core 提供。 + +SEO App 只提供: + +```text +Resources +Actions +Skills +Agents +Pages +Widgets +Reports +``` + +例如: + +```text +SEO +├── Overview +├── Websites +├── Keywords +├── Content +├── Backlinks +├── Reports +└── Agent +``` + +--- + +# 54. App Fork 模式 + +DevOS 必须支持: + +```text +DevOS Core + ↓ +Starter App +``` + +开发者可以: + +```text +Fork DevOS Starter +``` + +然后: + +```text +Remove unused Apps +Remove unused Plugins +Add custom modules +``` + +形成: + +```text +My Product +``` + +而不是: + +```text +必须运行完整 DevOS +``` + +--- + +# 55. Core / Starter / Full Distribution + +建议提供三种发行模式。 + +## Core + +```text +DevOS Core +``` + +只包含: + +```text +Identity +Resource +Action +Task +Plugin +Agent +MCP +UI Shell +``` + +--- + +## Starter + +```text +DevOS Starter +``` + +包含: + +```text +Core ++ +基础 Dashboard ++ +基础 Settings ++ +示例 Plugin +``` + +--- + +## Full + +```text +DevOS Full +``` + +包含: + +```text +Core ++ +多个 App ++ +常用 Plugins +``` + +--- + +# 56. 不允许 Core 与 App 强耦合 + +错误: + +```ts +import SEOWebsitePage from +"@devos/seo/pages/Website"; +``` + +然后 Core Dashboard 写死 SEO。 + +正确: + +```text +SEO App + ↓ +App Registry + ↓ +Route Registry + ↓ +Navigation Registry + ↓ +UI Shell +``` + +Core 不需要知道: + +```text +SEO +GitHub +Cloudflare +CRM +``` + +具体存在什么 App。 + +--- + +# 57. App 间集成 + +App 不应该直接互相 import 内部业务代码。 + +例如: + +```text +SEO App + ↓ +Browser Plugin +``` + +应该: + +```text +SEO App + ↓ +Capability / Action + ↓ +Browser Action +``` + +例如: + +```text +browser.open +``` + +这样: + +```text +Browser Plugin +``` + +不存在时: + +```text +Capability unavailable +``` + +SEO App 仍然可以正常运行。 + +--- + +# 58. UI → Capability + +UI 可以展示 Capability: + +```text +Capability: +browser.open +``` + +然后: + +```ts +executeAction({ + actionId: "browser.open", + input: { + url: "https://example.com" + } +}); +``` + +API Client 最终: + +```text +POST /api/actions/execute +``` + +或者: + +```text +POST /api/actions/browser.open +``` + +但后端必须统一进入: + +```text +Action Runtime +``` + +--- + +# 59. API Client + +前端建议统一: + +```ts +devos.api +``` + +例如: + +```ts +devos.api.resources.list(...) +devos.api.resources.get(...) +devos.api.actions.execute(...) +devos.api.tasks.get(...) +devos.api.agents.createGoal(...) +devos.api.search(...) +``` + +UI Component 不应该自己拼接 API URL。 + +--- + +# 60. Notification + +所有: + +```text +Action +Task +Agent +Plugin +System Event +``` + +都可以产生 Notification。 + +统一: + +```text +Notification Center +``` + +例如: + +```text +✓ SEO Scan completed + +⚠ GitHub token expires in 7 days + +✕ Deployment failed +``` + +Notification 来源可以是: + +```text +Event Bus +``` + +而不是组件之间互相调用。 + +--- + +# 61. Event → UI + +例如: + +```text +seo.website.scan.completed +``` + +Event Bus: + +```text +Event + ↓ +Notification + ↓ +Query Invalidation + ↓ +Widget Refresh +``` + +例如: + +```text +Website Scan +完成 + ↓ +Website Detail 自动刷新 + ↓ +Dashboard SEO Issues 自动刷新 +``` + +--- + +# 62. Query Invalidation + +Action 成功后: + +```ts +queryClient.invalidateQueries({ + queryKey: ["resource", "seo.website"] +}); +``` + +但最好由 Action/Event Metadata 提供: + +```text +Action + ↓ +Events + ↓ +UI Query Invalidation +``` + +避免 UI 到处硬编码业务依赖。 + +--- + +# 63. Audit UI + +用户应该能够看到: + +```text +Activity +``` + +例如: + +```text +10:21 User started SEO Scan +10:21 Agent created Task +10:22 Website Scan running +10:23 Website Scan completed +10:23 Agent generated report +``` + +来自: + +```text +Audit ++ +Execution ++ +Event ++ +Agent Trace +``` + +--- + +# 64. Agent Trace UI + +Agent Trace: + +```text +Goal + ↓ +Plan + ↓ +Capability Discovery + ↓ +Action + ↓ +Task + ↓ +Execution + ↓ +Observation + ↓ +Evaluation + ↓ +Report +``` + +UI: + +```text +SEO Agent + +Goal: +检查 example.com SEO + +✓ Discover capabilities +✓ Scan website +✓ Analyze issues +✓ Generate report + +Result: +12 issues found + +[View Report] +``` + +不要展示模型隐藏 Chain-of-Thought。 + +只展示: + +```text +Decision Summary +Action +Input Summary +Result Summary +Reason / Status +``` + +--- + +# 65. Mobile / Responsive + +Shell 必须支持: + +```text +Desktop +Tablet +Mobile +``` + +但核心 Developer Work OS 优先: + +```text +Desktop +``` + +Mobile 主要支持: + +```text +Monitoring +Notifications +Task Status +Agent Chat +Approval +``` + +复杂: + +```text +Terminal +Table +Workflow +``` + +优先 Desktop。 + +--- + +# 66. Theme + +Core UI 支持: + +```text +Light +Dark +System +``` + +Plugin UI 必须使用 DevOS Design Tokens。 + +禁止 Plugin 自己创建完全独立的: + +```text +Color System +Typography System +Spacing System +``` + +否则整个 DevOS 会出现视觉碎片化。 + +--- + +# 67. Design Tokens + +统一: + +```text +colors +spacing +radius +typography +shadow +breakpoints +z-index +``` + +例如: + +```ts +devos.theme +``` + +Plugin 只能: + +```text +使用 Token +``` + +而不是覆盖整个 Theme。 + +--- + +# 68. Developer API + +最终开发者应该可以这样开发: + +```ts +export default definePlugin({ + id: "github", + + ui: { + routes: [ + { + path: "/plugins/github/repositories", + component: "repositories" + } + ], + + navigation: [ + { + title: "Repositories", + path: "/plugins/github/repositories" + } + ], + + widgets: [ + { + slot: "dashboard.main", + component: "pull_requests" + } + ] + } +}); +``` + +然后 Plugin 安装: + +```text +Install Plugin + ↓ +Registry + ↓ +UI automatically available +``` + +--- + +# 69. Plugin Page API + +Plugin Page: + +```ts +definePluginPage({ + id: "github.repositories", + + route: "/plugins/github/repositories", + + permission: "github.repository.read", + + component: GithubRepositoriesPage +}); +``` + +--- + +# 70. Widget API + +```ts +defineWidget({ + id: "github.pull_requests", + + slot: "dashboard.main", + + title: "Pull Requests", + + permission: "github.pull_request.read", + + component: PullRequestWidget +}); +``` + +--- + +# 71. Context Action API + +```ts +defineContextAction({ + id: "github.create_issue", + + resourceTypes: [ + "github.repository" + ], + + actionId: "github.issue.create" +}); +``` + +--- + +# 72. UI 与 Backend Contract + +前端和 Backend 不应该通过: + +```text +任意 JSON +``` + +随意通信。 + +必须定义: + +```text +Resource Schema +Action Input Schema +Action Output Schema +Task Schema +Execution Schema +Event Schema +Capability Schema +``` + +推荐: + +```text +Zod ++ +OpenAPI +``` + +前端可以生成: + +```text +TypeScript Types +API Client +Form Schema +``` + +--- + +# 73. UI Error Model + +统一 Error: + +```ts +interface DevOSError { + code: string; + + message: string; + + details?: unknown; + + retryable?: boolean; + + actionId?: string; + + executionId?: string; +} +``` + +UI 根据: + +```text +code +``` + +决定: + +```text +Toast +Modal +Inline Error +Retry Button +Login +Permission +``` + +--- + +# 74. Loading State + +禁止每个页面自己发明: + +```text +Loading... +Please wait... +Processing... +``` + +统一组件: + +```text +Loading +Skeleton +Progress +ActionProgress +TaskProgress +ExecutionStatus +``` + +--- + +# 75. Empty State + +Resource: + +```text +No websites yet. + +[Create Website] +``` + +Plugin: + +```text +GitHub is not connected. + +[Connect GitHub] +``` + +Agent: + +```text +No goals yet. + +[Create Goal] +``` + +Empty State 可以由 Resource/Plugin Metadata 提供。 + +--- + +# 76. Confirmation + +危险 Action: + +```text +Delete +Deploy +Merge +Rotate Credentials +Drop Database +``` + +必须由 Action Metadata 指定: + +```ts +requiresApproval: true +``` + +UI 显示: + +```text +Confirm +``` + +但真正的安全控制仍然在 Backend。 + +--- + +# 77. Approval UI + +统一: + +```text +/approvals +``` + +例如: + +```text +SEO Agent wants to: + +Publish 20 articles + +Risk: +Medium + +[Approve] +[Reject] +``` + +Approval: + +```text +Agent + ↓ +Action + ↓ +Approval Required + ↓ +Human + ↓ +Action Runtime +``` + +--- + +# 78. Command + Agent + +Command Palette 可以直接进入 Agent: + +```text +> optimize example.com +``` + +系统可以识别: + +```text +This is a Goal +``` + +然后: + +```text +Command + ↓ +Agent Goal +``` + +因此 Command Palette 不是简单: + +```text +route search +``` + +它也是 DevOS 的 Agent Entry Point。 + +--- + +# 79. UI Architecture + +推荐最终目录: + +```text +apps/ +└── web/ + +packages/ +├── ui/ +├── shell/ +├── registry/ +├── navigation/ +├── routing/ +├── resource-ui/ +├── action-ui/ +├── task-ui/ +├── agent-ui/ +├── plugin-ui/ +├── widget-ui/ +├── command/ +├── search/ +├── workspace/ +├── permissions/ +├── api-client/ +└── theme/ +``` + +--- + +# 80. Shell Package + +```text +packages/shell/ + +├── AppShell +├── Header +├── Sidebar +├── Workspace +├── Breadcrumb +├── CommandPalette +├── GlobalSearch +├── NotificationCenter +└── UserMenu +``` + +--- + +# 81. Registry Package + +```text +packages/registry/ + +├── app-registry.ts +├── module-registry.ts +├── route-registry.ts +├── navigation-registry.ts +├── widget-registry.ts +├── command-registry.ts +└── context-action-registry.ts +``` + +--- + +# 82. Resource UI Package + +```text +packages/resource-ui/ + +├── ResourceList +├── ResourceDetail +├── ResourceForm +├── ResourceCreate +├── ResourceEdit +├── ResourceActions +└── ResourceActivity +``` + +--- + +# 83. Agent UI Package + +```text +packages/agent-ui/ + +├── AgentList +├── AgentDetail +├── AgentChat +├── AgentGoal +├── AgentRun +├── AgentTrace +└── AgentApproval +``` + +--- + +# 84. Plugin UI Package + +```text +packages/plugin-ui/ + +├── PluginPage +├── PluginSettings +├── PluginWidget +├── PluginNavigation +├── PluginContextAction +└── PluginErrorBoundary +``` + +--- + +# 85. 不允许的架构 + +以下全部禁止: + +```text +❌ Plugin 修改 Sidebar.tsx + +❌ Plugin 修改 Core Router + +❌ UI 直接访问 Database + +❌ UI 直接调用第三方 API + +❌ UI 自己实现业务 Action + +❌ Agent UI 直接调用 Plugin API + +❌ Plugin 绕过 Permission + +❌ Frontend Permission 代替 Backend Permission + +❌ 每个 App 自己实现 Layout + +❌ 每个 Plugin 自己实现 Settings Framework + +❌ 每个 Plugin 自己实现 Notification + +❌ 每个 Plugin 自己实现 Task UI +``` + +--- + +# 86. 推荐架构 + +最终: + +```text + DevOS UI Shell + │ + ┌────────────────┼────────────────┐ + │ │ │ + Core UI App UI Plugin UI + │ │ │ + └────────────────┼────────────────┘ + │ + UI Registry + │ + ┌──────────┬───────────┼──────────┬───────────┐ + │ │ │ │ │ + Routes Navigation Widgets Commands Context + │ │ │ │ │ + └──────────┴───────────┼──────────┴───────────┘ + │ + API / Runtime + │ + ┌────────────────┼────────────────┐ + │ │ │ + Resource Action Agent + │ │ │ + └────────────────┼────────────────┘ + │ + DevOS Backend +``` + +--- + +# 87. 最重要的设计结论 + +DevOS UI 不是: + +```text +一个 Admin Dashboard +``` + +而是: + +```text +一个可扩展的 UI Runtime +``` + +核心能力: + +```text +Shell ++ +Registry ++ +Route ++ +Navigation ++ +Resource UI ++ +Action UI ++ +Task UI ++ +Agent UI ++ +Plugin UI ++ +Widget ++ +Command ++ +Context Action +``` + +最终实现: + +```text +安装 Plugin + ↓ +Plugin 注册 Resource + ↓ +Plugin 注册 Action + ↓ +Plugin 注册 Skill + ↓ +Plugin 注册 MCP + ↓ +Plugin 注册 Route + ↓ +Plugin 注册 Navigation + ↓ +Plugin 注册 Widget + ↓ +Plugin 注册 Settings + ↓ +Plugin 注册 Context Actions + ↓ +DevOS UI 自动获得完整功能 +``` + +Core 不需要修改。 + +--- + +# 88. Zcode 必须实现的 Acceptance Criteria + +## AC-01 + +可以动态注册 App: + +```text +AppRegistry.register() +``` + +并自动出现 Navigation。 + +--- + +## AC-02 + +可以动态注册 Plugin。 + +Plugin 安装后自动出现: + +```text +Route +Navigation +Settings +Widget +``` + +--- + +## AC-03 + +Plugin 禁用后: + +```text +Navigation 消失 +Route 不可访问 +Widget 不再显示 +``` + +且不能导致 Shell 崩溃。 + +--- + +## AC-04 + +实现: + +```text +Resource List +Resource Detail +Resource Create +Resource Edit +``` + +并能读取 Resource Metadata。 + +--- + +## AC-05 + +Resource Action 必须通过: + +```text +Action Runtime +``` + +执行。 + +--- + +## AC-06 + +实现: + +```text +Task Detail +Execution Detail +Progress +Logs +Output +``` + +--- + +## AC-07 + +实现: + +```text +Command Palette +``` + +至少支持: + +```text +Navigation +Action +Resource +Agent +``` + +--- + +## AC-08 + +实现: + +```text +Global Search +``` + +支持: + +```text +Resource +Task +Agent +Plugin +Action +``` + +--- + +## AC-09 + +实现: + +```text +Widget Slot +``` + +至少支持: + +```text +dashboard.main +dashboard.sidebar +resource.detail.toolbar +resource.list.toolbar +``` + +--- + +## AC-10 + +实现: + +```text +Context Action +``` + +例如: + +```text +seo.website + ↓ +Open Browser +Scan SEO +Ask Agent +``` + +--- + +## AC-11 + +实现: + +```text +Plugin Settings +``` + +Plugin 可以拥有自己的: + +```text +/settings/plugins/{pluginId} +``` + +--- + +## AC-12 + +实现: + +```text +PermissionGuard +``` + +并确保: + +> Frontend Permission 仅用于 UI,Backend Authorization 才是最终安全边界。 + +--- + +## AC-13 + +实现: + +```text +Agent Chat +Agent Goal +Agent Run +Agent Trace +Agent Approval +``` + +并与 DevOS Agent Runtime 对接。 + +--- + +## AC-14 + +实现: + +```text +Workspace Context +``` + +支持: + +```text +Organization +Project +Environment +``` + +--- + +## AC-15 + +实现 Plugin Error Boundary。 + +单个 Plugin 崩溃不能导致整个 DevOS Shell 崩溃。 + +--- + +## AC-16 + +实现 Lazy Loading。 + +Plugin UI 不应该在 DevOS 首屏全部加载。 + +--- + +## AC-17 + +实现完整 UI Registry: + +```text +AppRegistry +ModuleRegistry +RouteRegistry +NavigationRegistry +WidgetRegistry +CommandRegistry +ContextActionRegistry +``` + +--- + +## AC-18 + +至少完成以下 Demo: + +### Demo A + +安装: + +```text +GitHub Plugin +``` + +自动出现: + +```text +GitHub +├── Repositories +├── Issues +└── Settings +``` + +--- + +### Demo B + +GitHub Plugin 注册: + +```text +dashboard.main +``` + +Widget。 + +Dashboard 自动显示。 + +--- + +### Demo C + +SEO Website: + +```text +example.com +``` + +右上角自动出现: + +```text +Open Browser +Scan SEO +Ask Agent +``` + +--- + +### Demo D + +Command Palette: + +```text +Cmd/Ctrl + K +``` + +输入: + +```text +scan example.com +``` + +可以发现: + +```text +SEO Scan +``` + +并执行: + +```text +seo.website.scan +``` + +--- + +### Demo E + +Agent: + +```text +检查 example.com 的 SEO +``` + +UI 显示: + +```text +Goal + ↓ +Plan + ↓ +Action + ↓ +Task + ↓ +Execution + ↓ +Report +``` + +--- + +# 89. Zcode 开发优先级 + +严格按照: + +```text +P0 +├── UI Shell +├── Registry +├── Route +├── Navigation +├── Permission +├── API Client +└── Action UI + +P1 +├── Resource UI +├── Task UI +├── Plugin UI +├── Widget +├── Settings +└── Context Action + +P2 +├── Agent UI +├── Command Palette +├── Global Search +├── Workspace +└── Approval UI + +P3 +├── Advanced Dashboard +├── UI Marketplace +├── Dynamic UI Schema +└── Advanced Extension System +``` + +--- + +# 90. 最终 Golden Rule + +DevOS 前端必须遵守: + +```text +Shell 不知道业务 +App 不拥有 Shell +Plugin 不修改 Core +Module 不绕过 App +UI 不实现业务逻辑 +UI 不直接访问 DB +UI 不绕过 Action Runtime +Agent UI 不绕过 Agent Runtime +Frontend Permission 不等于 Security +``` + +真正的扩展模型: + +```text + DevOS Core + │ + UI Runtime + │ + ┌─────────────┼─────────────┐ + │ │ │ + App Plugin Agent + │ │ │ + └─────────────┼─────────────┘ + │ + Registry + │ + ┌─────────────┼─────────────┐ + │ │ │ + Route Navigation Widget + │ │ │ + └─────────────┼─────────────┘ + │ + Action Runtime + │ + DevOS Backend +``` + +最终目标: + +> **开发者只需要开发 Resource / Action / Skill / Plugin / App,而不需要重复开发 Admin、Layout、Navigation、Task、Agent、Settings、Permission、Search、Notification 等基础设施。** + +这才是 DevOS UI Shell 的核心价值。 diff --git a/Docs/DevOS-Platform-v2/08_PLUGIN_RUNTIME.md b/Docs/DevOS-Platform-v2/08_PLUGIN_RUNTIME.md new file mode 100644 index 0000000..12302ac --- /dev/null +++ b/Docs/DevOS-Platform-v2/08_PLUGIN_RUNTIME.md @@ -0,0 +1,4315 @@ +# DevOS Developer Work OS +## Plugin Runtime / Plugin Lifecycle / Extension Platform 设计规范 + +Version: 1.0 + +--- + +# 1. 文档目标 + +本文定义 DevOS Plugin Runtime。 + +Plugin Runtime 是 DevOS 最重要的扩展基础设施之一。 + +目标: + +> 任何一个成熟能力,都应该能够以 Plugin 的形式安装到 DevOS,而不是修改 DevOS Core。 + +例如: + +```text +GitHub +Cloudflare +Browser +Google Search Console +Docker +Kubernetes +SSH +SMTP +WordPress +OpenAI +Anthropic +``` + +都应该可以成为 Plugin。 + +Plugin 可以提供: + +```text +Resource +Action +Event +Skill +MCP +Workflow +Agent Profile +UI +Navigation +Widget +Settings +Command +Context Action +``` + +最终: + +```text +Plugin + ↓ +Plugin Runtime + ↓ +Registry + ├── Resource Registry + ├── Action Registry + ├── Capability Registry + ├── Skill Registry + ├── MCP Registry + └── UI Registry +``` + +--- + +# 2. Plugin 的核心定义 + +Plugin: + +> 一个拥有明确 Manifest、版本、依赖、权限、能力、生命周期和扩展点的 DevOS Extension Package。 + +Plugin 不是简单的: + +```text +npm package +``` + +也不是简单的: + +```text +UI module +``` + +而是: + +```text +Code ++ +Manifest ++ +Capabilities ++ +Resources ++ +Actions ++ +UI ++ +Configuration ++ +Permissions ++ +Lifecycle +``` + +--- + +# 3. Plugin Architecture + +最终: + +```text + DevOS Core + │ + Plugin Runtime + │ + ┌──────────┼──────────┐ + │ │ │ + Registry Lifecycle Policy + │ │ │ + └──────────┼──────────┘ + │ + Installed Plugins + │ + ┌────────────────┼────────────────┐ + │ │ │ + GitHub Browser Cloudflare + │ │ │ + Resource Resource Resource + Action Action Action + Skill Skill Skill + MCP MCP MCP + UI UI UI +``` + +--- + +# 4. Plugin Manifest + +每个 Plugin 必须拥有 Manifest。 + +推荐: + +```ts +export interface PluginManifest { + id: string; + + name: string; + + displayName?: string; + + description?: string; + + version: string; + + author?: string; + + homepage?: string; + + license?: string; + + icon?: string; + + category?: string; + + runtime: PluginRuntimeConfig; + + dependencies?: PluginDependency[]; + + permissions?: PluginPermission[]; + + capabilities?: PluginCapabilityRef[]; + + resources?: PluginResourceRef[]; + + actions?: PluginActionRef[]; + + skills?: PluginSkillRef[]; + + mcp?: PluginMCPConfig; + + ui?: PluginUIManifest; + + settings?: PluginSettingsManifest; + + metadata?: Record; +} +``` + +--- + +# 5. Plugin ID + +Plugin ID 必须: + +- 全局唯一 +- 稳定 +- 不随版本变化 +- 不包含版本号 + +例如: + +```text +github +browser +cloudflare +docker +kubernetes +wordpress +``` + +禁止: + +```text +github-v2 +github-2026 +github-plugin-new +``` + +版本由: + +```text +version +``` + +单独管理。 + +--- + +# 6. Plugin Namespace + +所有 Plugin 产生的资源、Action、Skill 必须拥有 namespace。 + +例如: + +```text +github.repository +github.issue +github.pull_request + +github.repository.create +github.issue.create + +github.code_review +``` + +Browser: + +```text +browser.session +browser.page + +browser.open +browser.navigate + +browser.research +``` + +禁止 Plugin 创建: + +```text +user +settings +task +agent +``` + +这种容易与 Core 冲突的全局 ID。 + +--- + +# 7. Plugin 类型 + +Plugin Runtime 支持不同类型。 + +```ts +type PluginType = + | "integration" + | "provider" + | "automation" + | "developer" + | "ai" + | "storage" + | "ui" + | "composite"; +``` + +例如: + +```text +GitHub +→ integration + +OpenAI +→ provider + +Browser +→ automation + +Docker +→ developer + +SEO Analyzer +→ ai +``` + +大多数 Plugin 可以使用: + +```text +composite +``` + +因为同时包含: + +```text +Resource +Action +Skill +UI +MCP +``` + +--- + +# 8. Plugin Source + +Plugin 来源: + +```ts +type PluginSource = + | "builtin" + | "local" + | "workspace" + | "marketplace" + | "git" + | "npm" + | "url"; +``` + +例如: + +```text +DevOS Core Plugin +→ builtin + +本地开发插件 +→ local + +公司内部插件 +→ workspace + +Marketplace +→ marketplace +``` + +--- + +# 9. Plugin Installation + +安装流程: + +```text +Install Plugin + ↓ +Resolve Manifest + ↓ +Check Version + ↓ +Resolve Dependencies + ↓ +Check Compatibility + ↓ +Validate Permissions + ↓ +Install Package + ↓ +Register Plugin + ↓ +Run Migration + ↓ +Initialize + ↓ +Enable +``` + +必须支持: + +```text +Install +Uninstall +Enable +Disable +Upgrade +Rollback +``` + +--- + +# 10. Plugin 状态机 + +Plugin 状态: + +```ts +type PluginStatus = + | "available" + | "installing" + | "installed" + | "enabling" + | "enabled" + | "disabling" + | "disabled" + | "upgrading" + | "failed" + | "uninstalling"; +``` + +状态转换: + +```text +available + ↓ +installing + ↓ +installed + ↓ +enabling + ↓ +enabled +``` + +禁用: + +```text +enabled + ↓ +disabling + ↓ +disabled +``` + +升级: + +```text +enabled + ↓ +upgrading + ↓ +enabled +``` + +失败: + +```text +installing + ↓ +failed +``` + +--- + +# 11. Plugin Lifecycle + +Plugin 生命周期: + +```text +Discovery + ↓ +Install + ↓ +Validate + ↓ +Load + ↓ +Initialize + ↓ +Enable + ↓ +Running + ↓ +Disable + ↓ +Unload + ↓ +Uninstall +``` + +Plugin Runtime 必须提供生命周期 Hook: + +```ts +interface PluginLifecycle { + onInstall?(ctx: PluginContext): Promise; + + onLoad?(ctx: PluginContext): Promise; + + onInitialize?(ctx: PluginContext): Promise; + + onEnable?(ctx: PluginContext): Promise; + + onDisable?(ctx: PluginContext): Promise; + + onUnload?(ctx: PluginContext): Promise; + + onUninstall?(ctx: PluginContext): Promise; +} +``` + +--- + +# 12. Install 与 Enable 必须分离 + +这是非常重要的设计。 + +安装: + +```text +Package exists +``` + +启用: + +```text +Plugin is active +``` + +例如: + +```text +GitHub Plugin +Status: Installed +``` + +但: + +```text +Enabled: false +``` + +此时: + +```text +Resource +Action +Skill +MCP +UI +``` + +都不应该正常提供运行能力。 + +--- + +# 13. Disable Plugin + +Disable 后: + +```text +Plugin + ↓ +Unregister Runtime Capabilities + ↓ +Unregister UI + ↓ +Stop Background Jobs + ↓ +Stop Event Subscriptions + ↓ +Close Connections +``` + +但是: + +> Plugin 数据默认不能删除。 + +例如: + +```text +GitHub Plugin disabled +``` + +以下仍然存在: + +```text +github.repository +github.issue +historical executions +audit logs +settings +credentials references +``` + +只是新的运行能力不可用。 + +--- + +# 14. Uninstall Plugin + +Uninstall 是更危险的操作。 + +默认: + +```text +Uninstall + ≠ +Delete Plugin Data +``` + +推荐: + +```text +Uninstall Plugin + ↓ +Disable + ↓ +Unload + ↓ +Remove Runtime + ↓ +Keep Data +``` + +用户明确选择: + +```text +Delete Plugin Data +``` + +才执行数据删除。 + +--- + +# 15. Plugin Data Policy + +Manifest 可以定义: + +```ts +interface PluginDataPolicy { + canDeleteData: boolean; + + dataResources?: string[]; + + preserveOnUninstall?: boolean; +} +``` + +默认: + +```text +preserveOnUninstall = true +``` + +防止误删数据。 + +--- + +# 16. Plugin Dependencies + +Plugin 可以依赖其他 Plugin。 + +例如: + +```text +SEO Plugin + ↓ +Browser Plugin + ↓ +Browser Runtime +``` + +Manifest: + +```ts +{ + dependencies: [ + { + pluginId: "browser", + version: "^1.0.0", + optional: true + } + ] +} +``` + +--- + +# 17. Dependency Types + +支持: + +```text +required +optional +peer +``` + +例如: + +```text +required: +github + +optional: +browser + +peer: +ai provider +``` + +--- + +# 18. Dependency Resolution + +安装: + +```text +Install SEO Plugin +``` + +Runtime: + +```text +SEO + ↓ +Browser >= 1.2 + ↓ +AI Provider >= 2.0 +``` + +如果依赖缺失: + +```text +Dependency missing +``` + +应该明确提示: + +```text +SEO Plugin requires Browser Plugin >= 1.2 + +[Install Dependency] +``` + +而不是启动后才报错。 + +--- + +# 19. Dependency Cycle + +必须检测: + +```text +Plugin A + ↓ +Plugin B + ↓ +Plugin A +``` + +禁止循环依赖。 + +安装时直接失败: + +```text +PLUGIN_DEPENDENCY_CYCLE +``` + +--- + +# 20. Compatibility + +Plugin Manifest 可以声明: + +```ts +interface PluginRuntimeConfig { + devosVersion?: string; + + nodeVersion?: string; + + runtimeVersion?: string; +} +``` + +例如: + +```text +DevOS >= 1.5 < 2.0 +``` + +如果当前版本不兼容: + +```text +PLUGIN_INCOMPATIBLE +``` + +禁止强制启动。 + +--- + +# 21. Plugin Version + +遵循 SemVer: + +```text +MAJOR.MINOR.PATCH +``` + +例如: + +```text +1.0.0 +1.2.0 +1.2.3 +2.0.0 +``` + +规则: + +```text +PATCH +Bug fix + +MINOR +Backward compatible feature + +MAJOR +Breaking change +``` + +--- + +# 22. Plugin Upgrade + +升级: + +```text +Current: +github 1.4.0 + +Target: +github 1.5.0 +``` + +流程: + +```text +Check + ↓ +Backup Metadata + ↓ +Disable + ↓ +Migration + ↓ +Load New Version + ↓ +Validate + ↓ +Enable +``` + +如果失败: + +```text +Rollback +``` + +--- + +# 23. Migration + +Plugin 可以定义 Migration: + +```ts +interface PluginMigration { + version: string; + + up(ctx: MigrationContext): Promise; + + down?(ctx: MigrationContext): Promise; +} +``` + +例如: + +```text +1.0.0 + ↓ +1.1.0 + ↓ +1.2.0 +``` + +执行: + +```text +1.0 → 1.1 +1.1 → 1.2 +``` + +而不是直接假设数据库已经是最新状态。 + +--- + +# 24. Migration 原则 + +Migration 必须: + +- 可追踪 +- 幂等 +- 有版本 +- 有日志 +- 可失败恢复 +- 不直接依赖 UI + +禁止: + +```text +Plugin startup + ↓ +偷偷修改 DB +``` + +所有结构变化必须通过 Migration。 + +--- + +# 25. Plugin Runtime Context + +Plugin 不应该直接访问整个 DevOS Runtime。 + +提供: + +```ts +interface PluginContext { + pluginId: string; + + version: string; + + logger: Logger; + + config: PluginConfigService; + + registry: PluginRegistry; + + events: EventBus; + + actions: ActionRuntime; + + resources: ResourceRuntime; + + tasks: TaskRuntime; + + secrets: SecretReferenceService; + + storage: PluginStorage; + + permissions: PermissionService; +} +``` + +--- + +# 26. Plugin Registry + +Plugin Registry: + +```ts +interface PluginRegistry { + register(plugin: Plugin): Promise; + + unregister(pluginId: string): Promise; + + get(pluginId: string): Plugin | undefined; + + list(): Plugin[]; + + enable(pluginId: string): Promise; + + disable(pluginId: string): Promise; +} +``` + +--- + +# 27. Plugin Registry 不等于 Capability Registry + +必须区分: + +```text +Plugin Registry +``` + +负责: + +```text +Plugin 是否安装 +Plugin 是否启用 +Plugin 版本 +Plugin 状态 +Plugin 依赖 +``` + +而: + +```text +Capability Registry +``` + +负责: + +```text +Plugin 提供什么能力 +``` + +关系: + +```text +Plugin Registry + ↓ +Plugin + ↓ +Capability Registry + ↓ +Capabilities +``` + +--- + +# 28. Plugin 注册 Resource + +Plugin: + +```ts +registerResource({ + id: "github.repository" +}); +``` + +最终: + +```text +Resource Registry +``` + +获得: + +```text +github.repository +``` + +--- + +# 29. Plugin 注册 Action + +```ts +registerAction({ + id: "github.repository.create" +}); +``` + +最终: + +```text +Action Registry +``` + +获得: + +```text +github.repository.create +``` + +执行: + +```text +Action Runtime +``` + +--- + +# 30. Plugin 注册 Skill + +```ts +registerSkill({ + id: "github.code_review" +}); +``` + +最终: + +```text +Skill Registry +``` + +Agent 自动可以发现: + +```text +github.code_review +``` + +无需修改 Agent Runtime。 + +--- + +# 31. Plugin 注册 MCP + +Plugin 可以提供 MCP: + +```ts +mcp.registerServer({ + id: "github", + tools: [...] +}); +``` + +但 MCP Tool 最终必须: + +```text +MCP + ↓ +Capability + ↓ +Action Runtime +``` + +禁止: + +```text +MCP Tool + ↓ +直接 DB/API +``` + +--- + +# 32. Plugin 注册 UI + +Plugin 可以注册: + +```text +Route +Navigation +Widget +Settings +Command +Context Action +``` + +通过: + +```text +UI Registry +``` + +而不是修改: + +```text +Core React Source +``` + +--- + +# 33. Plugin Settings + +每个 Plugin 可以定义: + +```ts +interface PluginSettingsManifest { + schema: JSONSchema; + + scopes?: ( + | "global" + | "organization" + | "project" + | "user" + )[]; + + ui?: SettingsUIConfig; +} +``` + +例如 GitHub: + +```text +Global: +GitHub API URL + +Organization: +Default GitHub Organization + +User: +OAuth Account +``` + +--- + +# 34. Configuration Scope + +配置支持: + +```text +Global +Organization +Project +User +Environment +``` + +优先级: + +```text +Global + ↓ +Organization + ↓ +Project + ↓ +Environment + ↓ +User +``` + +具体优先级必须由配置系统统一定义。 + +Plugin 不应该自己实现一套配置优先级。 + +--- + +# 35. Plugin Secrets + +Plugin 需要: + +```text +API Key +OAuth Token +Private Key +Webhook Secret +``` + +只能使用: + +```text +Secret Reference +``` + +例如: + +```ts +{ + githubToken: { + secretRef: "secret://github/token" + } +} +``` + +禁止在 Manifest 中保存: + +```text +token: "ghp_xxx" +``` + +--- + +# 36. Credential Connection + +推荐建立: + +```text +Connection +``` + +抽象。 + +例如: + +```text +GitHub Connection +Cloudflare Connection +OpenAI Connection +AWS Connection +``` + +Plugin 使用: + +```ts +connectionId +``` + +而不是直接获取明文 Token。 + +--- + +# 37. Plugin Permissions + +Plugin 本身必须声明需要什么权限。 + +例如: + +```text +github.repository.read +github.repository.write +network.outbound +secret.read +filesystem.read +``` + +Manifest: + +```ts +permissions: [ + "network.outbound", + "secret.read" +] +``` + +--- + +# 38. Permission Approval + +安装 Plugin: + +```text +GitHub Plugin requests: + +✓ Network Access +✓ Secret Access +✓ Repository Read +✓ Repository Write +``` + +用户/管理员: + +```text +[Allow] +[Cancel] +``` + +对于 Organization: + +```text +只有 Org Admin +``` + +可以批准 Organization Scope 权限。 + +--- + +# 39. Plugin Permission 不等于 User Permission + +必须区分: + +```text +Plugin Permission +``` + +与: + +```text +User Permission +``` + +例如: + +```text +Plugin: +network.outbound + +User: +github.repository.read +``` + +两者都必须满足: + +```text +Plugin allowed ++ +User allowed +``` + +Action 才能执行。 + +--- + +# 40. Permission Chain + +完整权限: + +```text +User + ↓ +Organization Policy + ↓ +Plugin Permission + ↓ +Action Permission + ↓ +Resource Scope + ↓ +Action Runtime +``` + +任何一层拒绝: + +```text +DENIED +``` + +--- + +# 41. Plugin Isolation + +Plugin 默认应该是: + +```text +Capability Isolation +``` + +而不是: + +```text +完全信任 +``` + +Plugin 不应该自动获得: + +```text +所有 DB +所有 Secrets +所有 Filesystem +所有 Network +所有 Actions +``` + +--- + +# 42. Plugin Storage + +Plugin 如果需要自己的数据: + +```text +PluginStorage +``` + +例如: + +```text +plugin_data/github/* +plugin_data/browser/* +``` + +推荐: + +```ts +storage.get() +storage.set() +storage.delete() +storage.query() +``` + +而不是: + +```ts +plugin + ↓ +直接 Prisma +``` + +--- + +# 43. Plugin Database + +对于大型 Plugin,可以声明自己的数据库模型: + +```text +github.repository +github.issue +``` + +但这些仍然必须通过: + +```text +Resource Registry +``` + +暴露。 + +Plugin 内部可以使用 Prisma Repository。 + +但是: + +> UI / Agent / MCP / API 不允许绕过 Resource/Action Runtime。 + +--- + +# 44. Plugin Background Jobs + +Plugin 可以创建: + +```text +Task +Job +Scheduler +``` + +例如 GitHub Plugin: + +```text +Every 10 minutes + ↓ +Sync Repositories +``` + +但是: + +```text +Plugin + ↓ +Task Runtime + ↓ +Job Queue +``` + +禁止自己偷偷创建第二套 Queue。 + +--- + +# 45. Plugin Event Subscription + +Plugin 可以订阅: + +```text +Event Bus +``` + +例如: + +```text +github.pull_request.created +``` + +或者: + +```text +task.completed +``` + +注册: + +```ts +events.subscribe( + "task.completed", + handler +); +``` + +--- + +# 46. Plugin Event 发布 + +Plugin 也可以发布: + +```text +github.repository.synced +github.pull_request.updated +``` + +事件必须: + +```ts +{ + id, + type, + source, + timestamp, + actor, + organizationId, + projectId, + payload +} +``` + +--- + +# 47. Event 与 Action + +推荐: + +```text +Action + ↓ +Execution + ↓ +Event +``` + +例如: + +```text +github.repository.sync + ↓ +Execution completed + ↓ +github.repository.synced +``` + +其他 Plugin 可以监听。 + +--- + +# 48. Plugin Health Check + +Plugin Runtime 必须支持: + +```text +Health +Status +Diagnostics +``` + +例如: + +```text +GitHub Plugin + +Status: +Healthy + +Connection: +Connected + +API: +OK + +Last Sync: +2 min ago +``` + +--- + +# 49. Plugin Health Contract + +```ts +interface PluginHealth { + status: + | "healthy" + | "degraded" + | "unhealthy" + | "unknown"; + + message?: string; + + checks?: HealthCheck[]; +} +``` + +--- + +# 50. Plugin Diagnostics + +管理员可以看到: + +```text +Plugin +├── Version +├── Status +├── Dependencies +├── Permissions +├── Configuration +├── Connections +├── Health +├── Events +├── Tasks +├── Errors +└── Logs +``` + +--- + +# 51. Plugin Logs + +Plugin Logger: + +```ts +logger.info(...) +logger.warn(...) +logger.error(...) +logger.debug(...) +``` + +日志必须包含: + +```text +pluginId +requestId +executionId +taskId +organizationId +``` + +这样可以追踪: + +```text +User + ↓ +Agent + ↓ +Plugin + ↓ +Action + ↓ +Execution +``` + +--- + +# 52. Plugin Metrics + +Plugin 可以产生: + +```text +Counters +Gauges +Histograms +``` + +例如: + +```text +github.api.requests +github.api.errors +github.sync.duration +github.repositories.synced +``` + +统一进入: + +```text +Observability Runtime +``` + +--- + +# 53. Plugin Rate Limit + +Plugin Action 可以声明: + +```ts +rateLimit: { + requests: 100, + window: "1m" +} +``` + +但真正的 Rate Limit 应由: + +```text +Action Runtime +``` + +统一执行。 + +Plugin 只是声明策略。 + +--- + +# 54. Plugin Timeout + +Action 可以声明: + +```text +timeoutMs +``` + +例如: + +```text +browser.navigate +timeout: 30s +``` + +最终由: + +```text +Action Runtime +``` + +执行。 + +--- + +# 55. Plugin Retry + +Plugin 可以声明: + +```ts +retry: { + maxAttempts: 3, + backoff: "exponential" +} +``` + +但: + +> Retry 由 Task / Action Runtime 管理。 + +Plugin 不应该自己写: + +```text +while retry... +``` + +形成第二套执行系统。 + +--- + +# 56. Plugin Error Isolation + +Plugin 错误: + +```text +GitHub API failed +``` + +不能导致: + +```text +DevOS Core failed +``` + +错误必须被包装为: + +```text +PluginError +``` + +例如: + +```ts +{ + code: "GITHUB_API_RATE_LIMIT", + pluginId: "github", + retryable: true +} +``` + +--- + +# 57. Plugin UI Error Isolation + +前端: + +```text +Plugin UI + ↓ +Error Boundary +``` + +如果: + +```text +GitHub UI crashed +``` + +只能影响: + +```text +GitHub UI +``` + +不能导致: + +```text +整个 Shell 崩溃 +``` + +具体 UI 规范见: + +```text +07_UI_SHELL_APP_MODULE.md +``` + +--- + +# 58. Plugin API + +Plugin Runtime 对开发者提供: + +```ts +definePlugin({ + manifest, + lifecycle, + resources, + actions, + skills, + mcp, + ui, + settings +}); +``` + +例如: + +```ts +export default definePlugin({ + manifest: { + id: "github", + name: "GitHub", + version: "1.0.0" + }, + + resources: [ + repositoryResource + ], + + actions: [ + createRepositoryAction + ], + + skills: [ + codeReviewSkill + ] +}); +``` + +--- + +# 59. Plugin SDK + +建议: + +```text +packages/plugin-sdk/ +``` + +提供: + +```text +definePlugin() +defineResource() +defineAction() +defineSkill() +defineWidget() +definePage() +defineCommand() +defineContextAction() +defineSettings() +defineMCP() +``` + +Plugin 开发者不需要知道 DevOS 内部实现。 + +--- + +# 60. Plugin SDK 原则 + +SDK 应该: + +```text +简单 +稳定 +类型安全 +版本化 +``` + +Plugin 不应该依赖: + +```text +packages/internal/* +``` + +只能依赖: + +```text +@devos/plugin-sdk +``` + +以及明确公开的 SDK Package。 + +--- + +# 61. Plugin API Version + +Plugin API 必须版本化: + +```text +Plugin SDK v1 +Plugin SDK v2 +``` + +Manifest: + +```ts +apiVersion: "1" +``` + +Core 可以同时兼容: + +```text +v1 +v2 +``` + +--- + +# 62. Plugin Marketplace + +未来可以提供: + +```text +Plugin Marketplace +``` + +Plugin 信息: + +```text +Name +Description +Version +Author +License +Downloads +Rating +Compatibility +Permissions +Dependencies +``` + +但 Marketplace 不是 Plugin Runtime 的必要依赖。 + +DevOS 即使完全离线: + +```text +local plugin +``` + +也应该正常工作。 + +--- + +# 63. Plugin Signature + +生产环境推荐支持: + +```text +Plugin Signature +``` + +安装: + +```text +Package + ↓ +Signature Verification + ↓ +Trusted Publisher + ↓ +Install +``` + +管理员可以设置: + +```text +Only trusted plugins +``` + +--- + +# 64. Plugin Security Policy + +Organization 可以设置: + +```text +Allowed Plugins +Denied Plugins +Allowed Publishers +Required Signature +Required Approval +Allowed Permissions +``` + +例如: + +```text +禁止所有 Plugin 使用 filesystem.write +``` + +即使 Plugin Manifest 声明: + +```text +filesystem.write +``` + +也必须被: + +```text +Organization Policy +``` + +拒绝。 + +--- + +# 65. Plugin Environment + +Plugin 可以区分: + +```text +development +staging +production +``` + +例如: + +```text +GitHub Plugin +``` + +不同环境使用不同 Connection。 + +Plugin 不应该自己实现: + +```text +if production ... +``` + +而使用: + +```text +Environment Context +``` + +--- + +# 66. Multi-Tenant + +DevOS 支持: + +```text +Organization A +Organization B +``` + +同一个 Plugin 可以: + +```text +Installed once +``` + +但是: + +```text +Configuration +Credentials +Permissions +Resources +Tasks +``` + +必须支持 Organization Scope。 + +例如: + +```text +GitHub Plugin +├── Org A +│ └── GitHub Connection A +│ +└── Org B + └── GitHub Connection B +``` + +禁止跨 Organization 泄露。 + +--- + +# 67. Plugin Resource Ownership + +Resource: + +```text +github.repository +``` + +必须有: + +```text +organizationId +projectId +``` + +或者明确的 Scope。 + +Resource Runtime 必须检查: + +```text +Actor ++ +Organization ++ +Project ++ +Resource +``` + +--- + +# 68. Plugin Runtime 与 Agent + +Agent 不直接读取: + +```text +Plugin +``` + +而读取: + +```text +Capability Registry +``` + +例如: + +```text +Install GitHub Plugin + ↓ +github.repository.create + ↓ +Capability Registry + ↓ +Agent Discovery +``` + +Agent 无需修改。 + +--- + +# 69. Plugin Runtime 与 MCP + +MCP: + +```text +Plugin + ↓ +MCP Server + ↓ +Capability + ↓ +Action Runtime +``` + +External MCP: + +```text +External MCP + ↓ +MCP Client + ↓ +Capability Adapter + ↓ +DevOS Runtime +``` + +统一模型。 + +--- + +# 70. Plugin Runtime 与 UI + +Plugin: + +```text +Plugin Manifest + ↓ +UI Manifest + ↓ +UI Registry + ↓ +Route +Navigation +Widget +Settings +Command +Context Action +``` + +见: + +```text +07_UI_SHELL_APP_MODULE.md +``` + +--- + +# 71. Plugin Runtime 与 Task + +Plugin 不创建: + +```text +PluginTask +PluginQueue +PluginWorker +``` + +而使用: + +```text +Task Runtime +Job Runtime +Queue Runtime +Worker Runtime +``` + +例如: + +```text +GitHub Sync + ↓ +Task + ↓ +Jobs + ↓ +Workers +``` + +--- + +# 72. Plugin Runtime 与 Scheduler + +Plugin 可以声明: + +```ts +schedule({ + id: "github.sync", + cron: "*/10 * * * *", + actionId: "github.repository.sync" +}); +``` + +Scheduler 创建: + +```text +Task +``` + +而不是 Plugin 自己执行。 + +--- + +# 73. Plugin Runtime 与 Audit + +所有 Plugin Action 自动进入: + +```text +Audit Runtime +``` + +例如: + +```text +User + ↓ +Agent + ↓ +github.repository.delete + ↓ +Action Runtime + ↓ +Audit +``` + +记录: + +```text +Actor +Plugin +Action +Resource +Input Summary +Result +Timestamp +Execution +``` + +--- + +# 74. Plugin Runtime 与 Observability + +统一: + +```text +Logs +Metrics +Traces +Audit +Execution +``` + +可以查询: + +```text +Plugin: github +``` + +看到: + +```text +Requests +Errors +Actions +Tasks +Executions +Latency +External API Calls +``` + +--- + +# 75. Plugin Runtime API + +推荐: + +```text +POST /api/plugins/install +POST /api/plugins/:id/enable +POST /api/plugins/:id/disable +POST /api/plugins/:id/upgrade +DELETE /api/plugins/:id + +GET /api/plugins +GET /api/plugins/:id +GET /api/plugins/:id/health +GET /api/plugins/:id/logs +GET /api/plugins/:id/metrics +``` + +但是 Controller 不实现 Plugin 业务逻辑。 + +统一进入: + +```text +Plugin Runtime +``` + +--- + +# 76. Plugin Service + +Backend: + +```text +packages/plugin/ +``` + +推荐: + +```text +plugin/ +├── plugin-registry.ts +├── plugin-loader.ts +├── plugin-installer.ts +├── plugin-lifecycle.ts +├── plugin-validator.ts +├── plugin-dependency.ts +├── plugin-migration.ts +├── plugin-config.ts +├── plugin-permission.ts +├── plugin-health.ts +├── plugin-storage.ts +├── plugin-security.ts +└── plugin-runtime.ts +``` + +--- + +# 77. Plugin Loader + +Loader 负责: + +```text +Locate Package + ↓ +Load Manifest + ↓ +Validate Manifest + ↓ +Load Module + ↓ +Verify SDK Version + ↓ +Create Plugin Context +``` + +禁止 Loader: + +```text +直接执行任意未知代码 +``` + +必须经过: + +```text +Security Policy +``` + +--- + +# 78. Plugin Installer + +Installer: + +```text +Resolve Source + ↓ +Download / Copy + ↓ +Verify Signature + ↓ +Verify Integrity + ↓ +Resolve Dependencies + ↓ +Install + ↓ +Migration +``` + +--- + +# 79. Plugin Runtime Directory + +推荐: + +```text +plugins/ +├── installed/ +│ ├── github/ +│ ├── browser/ +│ └── cloudflare/ +│ +├── cache/ +│ +└── manifests/ +``` + +具体路径可由部署环境配置。 + +不要将 Plugin 代码直接混入: + +```text +packages/core/ +``` + +--- + +# 80. Built-in Plugin + +部分 Plugin 可以随 DevOS 一起发布: + +```text +Core +├── identity +├── notification +├── task +├── agent +└── audit +``` + +但推荐仍然遵循: + +```text +Plugin Contract +``` + +这样: + +```text +Built-in Plugin +``` + +与: + +```text +External Plugin +``` + +使用相同生命周期。 + +--- + +# 81. Core Plugin 与真正 Core + +Core 必须保持最小化。 + +真正不可替代的: + +```text +Runtime +Database +Auth +Action +Resource +Task +Event +Plugin +``` + +属于: + +```text +Core +``` + +可插拔功能: + +```text +GitHub +Browser +Cloudflare +Docker +WordPress +``` + +属于: + +```text +Plugin +``` + +--- + +# 82. Composite Plugin + +Plugin 可以依赖多个 Plugin: + +```text +SEO Automation Plugin +├── Browser Plugin +├── Search Plugin +└── AI Plugin +``` + +但 Composite Plugin 不应该复制这些能力。 + +它只负责: + +```text +Workflow +Skill +Agent Profile +UI +``` + +调用: + +```text +Browser +Search +AI +``` + +提供的 Capability。 + +--- + +# 83. Plugin 与 App 的关系 + +App: + +```text +产品/业务领域 +``` + +Plugin: + +```text +扩展能力 +``` + +例如: + +```text +SEO App +``` + +可以使用: + +```text +Browser Plugin +Search Plugin +GSC Plugin +WordPress Plugin +``` + +App 不应该把这些功能复制进自己代码。 + +--- + +# 84. 一个 Plugin 可以服务多个 App + +例如: + +```text +Browser Plugin +``` + +同时服务: + +```text +SEO App +Content App +Research App +DevOps App +Agent +``` + +架构: + +```text +Browser Plugin + ↓ +Capability Registry + ↓ +SEO +Content +Research +Agent +``` + +这也是 DevOS 最重要的复用价值之一。 + +--- + +# 85. Plugin Discovery + +Agent / UI / Developer 都可以发现: + +```text +Installed Plugins +Available Plugins +Plugin Capabilities +``` + +例如: + +```text +Search: +browser +``` + +返回: + +```text +Browser Plugin + +Capabilities: +browser.open +browser.navigate +browser.screenshot + +Skills: +browser.research +``` + +--- + +# 86. Plugin Marketplace 不应该成为 Runtime + +Marketplace: + +```text +发现 +下载 +评分 +安装 +``` + +Plugin Runtime: + +```text +加载 +运行 +启停 +配置 +权限 +生命周期 +``` + +两者必须分离。 + +--- + +# 87. Plugin Failure Recovery + +如果 Plugin 启动失败: + +```text +Plugin + ↓ +Initialize + ↓ +FAILED +``` + +Runtime 应: + +```text +Mark failed + ↓ +Unregister capabilities + ↓ +Stop background tasks + ↓ +Record error + ↓ +Notify administrator +``` + +不要: + +```text +不断自动重启 +``` + +除非明确配置 Retry Policy。 + +--- + +# 88. Plugin Dependency Failure + +例如: + +```text +SEO Plugin + ↓ +Browser Plugin + ↓ +Browser failed +``` + +SEO Plugin 可以变成: + +```text +degraded +``` + +而不是: + +```text +整个 DevOS failed +``` + +--- + +# 89. Plugin Disable Impact + +Disable Plugin 时必须计算: + +```text +Dependent Plugins +``` + +例如: + +```text +Browser Plugin +``` + +被使用: + +```text +SEO Plugin +Research Plugin +``` + +系统应提示: + +```text +Disabling Browser will affect: + +SEO Plugin +Research Plugin + +[Continue] +[Cancel] +``` + +--- + +# 90. Plugin Upgrade Impact + +升级时同样检查: + +```text +Dependent Plugins +``` + +如果: + +```text +GitHub 2.0 +``` + +不兼容: + +```text +GitHub Automation Plugin +``` + +必须阻止升级或进入兼容升级流程。 + +--- + +# 91. Plugin State Persistence + +Plugin 状态必须持久化: + +```text +installed +enabled +version +configuration +permissions +dependencies +health +``` + +DevOS 重启: + +```text +Database + ↓ +Plugin Registry + ↓ +Restore Plugin State + ↓ +Load + ↓ +Enable +``` + +--- + +# 92. Plugin Installation Transaction + +安装过程应该尽量具有事务语义: + +```text +Validate + ↓ +Install + ↓ +Migration + ↓ +Register + ↓ +Enable +``` + +如果中途失败: + +```text +Rollback +``` + +避免: + +```text +Package installed ++ +DB migrated ++ +Plugin unusable +``` + +--- + +# 93. Plugin Lock File + +生产环境建议支持: + +```text +devos.plugins.lock +``` + +记录: + +```text +pluginId +version +source +integrity +dependencies +``` + +作用: + +```text +Development +→ lock + +Production +→ reproducible install +``` + +--- + +# 94. Plugin Development Mode + +开发模式: + +```text +devos plugin dev +``` + +支持: + +```text +Hot Reload +Manifest Reload +UI Reload +Logs +Diagnostics +``` + +开发 Plugin: + +```text +/home/dev/plugins/my-plugin +``` + +直接注册。 + +--- + +# 95. Plugin CLI + +建议提供: + +```text +devos plugin list + +devos plugin install github + +devos plugin uninstall github + +devos plugin enable github + +devos plugin disable github + +devos plugin upgrade github + +devos plugin doctor github + +devos plugin create my-plugin +``` + +CLI 必须调用: + +```text +Plugin Runtime +``` + +不能实现另一套 Plugin 管理逻辑。 + +--- + +# 96. Plugin Doctor + +例如: + +```text +devos plugin doctor github +``` + +输出: + +```text +Plugin: +github 1.4.0 + +✓ Manifest +✓ DevOS compatibility +✓ Dependencies +✓ Permissions +✓ Database +✓ Configuration +✓ Connection + +Health: +Healthy +``` + +--- + +# 97. Plugin Admin UI + +DevOS: + +```text +/settings/plugins +``` + +显示: + +```text +Plugins + +GitHub +Enabled +v1.4.0 +Healthy + +Browser +Enabled +v2.1.0 +Healthy + +Cloudflare +Disabled +v1.0.2 +``` + +操作: + +```text +Enable +Disable +Upgrade +Configure +Health +Logs +``` + +--- + +# 98. Plugin Detail UI + +Plugin Detail: + +```text +GitHub Plugin +──────────────────────── + +Version +1.4.0 + +Status +Enabled + +Health +Healthy + +Capabilities +18 + +Resources +5 + +Actions +11 + +Skills +2 + +MCP +1 + +Permissions +4 + +Dependencies +1 + +[Disable] +[Upgrade] +[Settings] +``` + +--- + +# 99. Plugin Runtime 与 UI Registry 的生命周期 + +启用: + +```text +Plugin Enable + ↓ +Register Resource + ↓ +Register Action + ↓ +Register Skill + ↓ +Register MCP + ↓ +Register Route + ↓ +Register Navigation + ↓ +Register Widget + ↓ +Register Command + ↓ +Register Context Action +``` + +禁用: + +```text +Plugin Disable + ↓ +Stop Jobs + ↓ +Unsubscribe Events + ↓ +Close Connections + ↓ +Unregister UI + ↓ +Unregister MCP + ↓ +Unregister Skills + ↓ +Unregister Actions + ↓ +Unregister Resources +``` + +--- + +# 100. Plugin Registry Consistency + +Plugin Registry 与其他 Registry 必须保持一致。 + +例如: + +```text +Plugin disabled +``` + +不能出现: + +```text +Plugin Registry: +disabled + +Action Registry: +github.repository.create ← still active +``` + +必须: + +```text +Plugin disabled + ↓ +All Plugin-owned registrations inactive +``` + +--- + +# 101. Ownership + +所有 Registry Entry 必须记录: + +```ts +{ + ownerType: "plugin", + ownerId: "github" +} +``` + +例如: + +```text +Action: +github.repository.create + +owner: +plugin:github +``` + +这样 Plugin Disable 时可以准确卸载。 + +--- + +# 102. Registration Metadata + +建议: + +```ts +interface RegistrationMetadata { + ownerType: + | "core" + | "app" + | "module" + | "plugin"; + + ownerId: string; + + version?: string; + + registeredAt: string; +} +``` + +--- + +# 103. 防止 Plugin 泄漏 + +如果 Plugin 被卸载: + +```text +所有 ownerId = github +``` + +的 Registry Entry 都必须被清理。 + +可以实现: + +```ts +registry.unregisterByOwner({ + ownerType: "plugin", + ownerId: "github" +}); +``` + +--- + +# 104. Plugin Runtime Golden Rule + +Plugin 可以: + +```text +提供能力 +注册能力 +消费能力 +扩展 UI +监听 Event +创建 Task +``` + +Plugin 不可以: + +```text +绕过 Runtime +绕过 Permission +绕过 Audit +绕过 Task Runtime +绕过 Action Runtime +直接修改 Core Registry +直接修改用户数据 +``` + +--- + +# 105. 最终 Plugin 执行链 + +标准业务: + +```text +User + ↓ +UI + ↓ +Action + ↓ +Action Runtime + ↓ +Plugin Action + ↓ +External API + ↓ +Execution + ↓ +Event + ↓ +UI / Agent +``` + +Agent: + +```text +User Goal + ↓ +Agent + ↓ +Capability Discovery + ↓ +Plugin Capability + ↓ +Action + ↓ +Action Runtime + ↓ +Plugin + ↓ +External System +``` + +MCP: + +```text +External Agent + ↓ +MCP Server + ↓ +Capability + ↓ +Action Runtime + ↓ +Plugin +``` + +--- + +# 106. 完整 Plugin Example + +GitHub Plugin: + +```text +github/ +├── manifest.ts +├── index.ts +│ +├── resources/ +│ ├── repository.ts +│ ├── issue.ts +│ └── pull-request.ts +│ +├── actions/ +│ ├── repository-create.ts +│ ├── repository-sync.ts +│ ├── issue-create.ts +│ └── pull-request-merge.ts +│ +├── skills/ +│ └── code-review.ts +│ +├── mcp/ +│ └── server.ts +│ +├── ui/ +│ ├── repositories.tsx +│ ├── issues.tsx +│ ├── settings.tsx +│ └── widgets/ +│ +├── migrations/ +│ ├── 1.1.0.ts +│ └── 1.2.0.ts +│ +└── tests/ +``` + +--- + +# 107. GitHub Manifest 示例 + +```ts +export default { + id: "github", + + name: "GitHub", + + version: "1.0.0", + + apiVersion: "1", + + runtime: { + devosVersion: ">=1.0.0" + }, + + permissions: [ + "network.outbound", + "secret.read" + ], + + dependencies: [], + + resources: [ + "github.repository", + "github.issue", + "github.pull_request" + ], + + actions: [ + "github.repository.create", + "github.repository.sync", + "github.issue.create", + "github.pull_request.merge" + ], + + skills: [ + "github.code_review" + ] +}; +``` + +--- + +# 108. Plugin Developer Experience + +开发者最终应该只需要: + +```text +devos plugin create github +``` + +得到: + +```text +manifest +resources +actions +skills +ui +tests +``` + +然后: + +```text +devos plugin dev +``` + +即可运行。 + +发布: + +```text +devos plugin build +devos plugin publish +``` + +--- + +# 109. Zcode 必须实现的 Package + +至少: + +```text +packages/plugin/ +├── types/ +├── registry/ +├── runtime/ +├── loader/ +├── installer/ +├── lifecycle/ +├── dependency/ +├── migration/ +├── config/ +├── permissions/ +├── storage/ +├── health/ +├── security/ +└── sdk/ +``` + +--- + +# 110. Zcode 必须实现的 Backend Services + +至少: + +```text +PluginService +PluginRegistry +PluginLoader +PluginInstaller +PluginLifecycleService +PluginDependencyService +PluginMigrationService +PluginConfigService +PluginPermissionService +PluginHealthService +PluginSecurityService +PluginStorageService +``` + +--- + +# 111. Zcode 必须实现的 API + +至少: + +```text +GET /api/plugins + +GET /api/plugins/:id + +POST /api/plugins/install + +POST /api/plugins/:id/enable + +POST /api/plugins/:id/disable + +POST /api/plugins/:id/upgrade + +DELETE /api/plugins/:id + +GET /api/plugins/:id/health + +GET /api/plugins/:id/logs + +GET /api/plugins/:id/metrics +``` + +--- + +# 112. Zcode 必须实现的 UI + +至少: + +```text +/settings/plugins + +/settings/plugins/:id + +/settings/plugins/:id/settings + +/settings/plugins/:id/health + +/settings/plugins/:id/logs +``` + +支持: + +```text +Install +Enable +Disable +Upgrade +Uninstall +Configure +Health +Logs +``` + +--- + +# 113. Acceptance Test 01 + +创建: + +```text +hello-plugin +``` + +安装。 + +结果: + +```text +Plugin Registry +→ hello-plugin installed +``` + +--- + +# 114. Acceptance Test 02 + +Enable: + +```text +hello-plugin +``` + +结果: + +```text +Action Registry +→ hello.hello +``` + +出现。 + +--- + +# 115. Acceptance Test 03 + +Disable: + +```text +hello-plugin +``` + +结果: + +```text +hello.hello +``` + +不可执行。 + +同时: + +```text +Navigation +Route +Widget +``` + +全部消失。 + +--- + +# 116. Acceptance Test 04 + +安装 Plugin: + +```text +github +``` + +自动注册: + +```text +Resources +Actions +Skills +MCP +UI +``` + +不修改 Core source。 + +--- + +# 117. Acceptance Test 05 + +卸载: + +```text +github +``` + +Plugin Runtime 清理: + +```text +Routes +Navigation +Widgets +Actions +Skills +MCP +Event Subscriptions +Scheduled Jobs +``` + +历史: + +```text +Tasks +Executions +Audit +``` + +仍然保留。 + +--- + +# 118. Acceptance Test 06 + +安装: + +```text +plugin-a +``` + +依赖: + +```text +plugin-b >= 1.2 +``` + +如果没有: + +```text +Installation blocked +``` + +并提示: + +```text +Missing dependency: +plugin-b >= 1.2 +``` + +--- + +# 119. Acceptance Test 07 + +测试循环依赖: + +```text +A → B +B → A +``` + +结果: + +```text +PLUGIN_DEPENDENCY_CYCLE +``` + +安装失败。 + +--- + +# 120. Acceptance Test 08 + +测试 Plugin Permission。 + +Plugin 请求: + +```text +secret.read +``` + +管理员拒绝。 + +结果: + +```text +Plugin installed +but cannot enable +``` + +或者: + +```text +Plugin capability unavailable +``` + +具体策略必须统一。 + +--- + +# 121. Acceptance Test 09 + +测试 Multi-Tenant: + +```text +Organization A +Organization B +``` + +GitHub Connection: + +```text +A → Token A +B → Token B +``` + +A 的 Action: + +```text +github.repository.sync +``` + +不能读取 B 的 Connection。 + +--- + +# 122. Acceptance Test 10 + +测试 Plugin Crash。 + +故意让: + +```text +github plugin +``` + +初始化失败。 + +结果: + +```text +GitHub Plugin → failed +``` + +但: + +```text +DevOS Shell → healthy +Other Plugins → healthy +Core → healthy +``` + +--- + +# 123. Acceptance Test 11 + +测试 Upgrade。 + +```text +github 1.0.0 + ↓ +github 1.1.0 +``` + +执行: + +```text +Migration + ↓ +Registry update + ↓ +Plugin enable +``` + +数据正常。 + +--- + +# 124. Acceptance Test 12 + +Migration 失败。 + +结果: + +```text +Upgrade failed +``` + +系统不能进入: + +```text +half-upgraded +``` + +状态。 + +必须进入: + +```text +failed +``` + +或者: + +```text +rollback +``` + +--- + +# 125. Acceptance Test 13 + +测试 Agent。 + +安装 GitHub Plugin。 + +输入: + +```text +帮我检查这个 GitHub Repository +``` + +Agent 能发现: + +```text +github.repository +github.repository.inspect +``` + +无需修改 Agent Runtime。 + +--- + +# 126. Acceptance Test 14 + +测试 MCP。 + +外部 Agent 调用: + +```text +github_repository_create +``` + +执行链必须: + +```text +MCP + ↓ +Capability + ↓ +Action Runtime + ↓ +Permission + ↓ +Plugin + ↓ +GitHub API + ↓ +Audit +``` + +不能: + +```text +MCP + ↓ +GitHub API +``` + +--- + +# 127. Acceptance Test 15 + +测试 UI。 + +安装 GitHub Plugin。 + +自动出现: + +```text +Plugins +└── GitHub + ├── Repositories + ├── Issues + └── Settings +``` + +无需修改: + +```text +Sidebar.tsx +Router.tsx +Dashboard.tsx +``` + +--- + +# 128. Acceptance Test 16 + +Plugin 注册 Widget: + +```text +dashboard.main +``` + +启用 Plugin: + +```text +Widget visible +``` + +禁用: + +```text +Widget invisible +``` + +--- + +# 129. Acceptance Test 17 + +Plugin 注册 Context Action: + +```text +github.repository +``` + +显示: + +```text +Create Issue +``` + +点击: + +```text +Action Runtime +``` + +执行。 + +--- + +# 130. Acceptance Test 18 + +CLI: + +```text +devos plugin list +``` + +与 UI: + +```text +/settings/plugins +``` + +显示完全一致的 Plugin Registry 数据。 + +CLI 和 UI 不得各自维护状态。 + +--- + +# 131. 最终架构 + +```text + DevOS Core + │ + Plugin Runtime + │ + ┌──────────────────────┼──────────────────────┐ + │ │ │ + Lifecycle Security Registry + │ │ │ + Install/Enable Permission Plugin Registry + Disable/Upgrade Isolation Capability Registry + Migration Secrets UI Registry + │ │ │ + └──────────────────────┼──────────────────────┘ + │ + Plugin SDK + │ + ┌──────────────┬───────┼────────┬──────────────┐ + │ │ │ │ │ + Resource Action Skill MCP UI + │ │ │ │ │ + └──────────────┴───────┼────────┴──────────────┘ + │ + DevOS Runtime + │ + ┌──────────────┬───────┼────────┬──────────────┐ + │ │ │ │ │ + Resource Action Task Event Agent + Runtime Runtime Runtime Bus Runtime +``` + +--- + +# 132. Plugin 的最终定位 + +Plugin 不是: + +```text +一个 npm package +``` + +Plugin 是: + +```text +DevOS 的能力扩展单元 +``` + +一个完整 Plugin 可以同时提供: + +```text +Resource ++ +Action ++ +Skill ++ +MCP ++ +Workflow ++ +UI ++ +Settings ++ +Widget ++ +Event +``` + +并通过统一 Runtime 接入: + +```text +Auth +Permission +Task +Queue +Audit +Observability +Agent +UI +``` + +--- + +# 133. 最重要的 Golden Rules + +```text +1. Plugin 不修改 Core。 + +2. Plugin 必须拥有 Manifest。 + +3. Plugin 必须拥有稳定 ID。 + +4. Plugin 必须拥有版本。 + +5. Plugin 必须拥有生命周期。 + +6. Install ≠ Enable。 + +7. Disable ≠ Uninstall。 + +8. Uninstall 默认不删除业务数据。 + +9. Plugin 必须声明 Dependencies。 + +10. Plugin 必须声明 Permissions。 + +11. Plugin Action 必须进入 Action Runtime。 + +12. Plugin Task 必须进入 Task Runtime。 + +13. Plugin Event 必须进入 Event Bus。 + +14. Plugin UI 必须进入 UI Registry。 + +15. Plugin MCP 不得绕过 Action Runtime。 + +16. Agent 不直接调用 Plugin。 + +17. Agent 通过 Capability Registry 使用 Plugin 能力。 + +18. Plugin 不应该创建自己的 Queue。 + +19. Plugin 不应该创建自己的权限系统。 + +20. Plugin 不应该创建自己的 Audit 系统。 + +21. Plugin 不应该创建自己的 Scheduler。 + +22. Plugin 不应该创建自己的 Notification 系统。 + +23. Plugin 不应该直接操作其他 Plugin 的数据。 + +24. Plugin 必须支持 Organization Scope。 + +25. Plugin 必须能够被独立禁用。 + +26. 单个 Plugin 崩溃不能导致 DevOS 崩溃。 + +27. Core 不应该知道具体 Plugin。 + +28. App 不应该复制 Plugin 能力。 + +29. Plugin 应该尽量提供 Capability,而不是绑定某个 App。 + +30. DevOS 的所有扩展最终都应该回到统一 Runtime。 +``` + +--- + +# 134. 最终 DevOS 扩展模型 + +至此,DevOS 的扩展体系形成: + +```text + DevOS Core + │ + ┌───────────────┼────────────────┐ + │ │ │ + App Plugin Agent + │ │ │ + Module Capability Goal + │ │ │ + └───────────────┼────────────────┘ + │ + Resource / Action + │ + Action Runtime + │ + ┌───────────────┼────────────────┐ + │ │ │ + Task Event Audit + │ │ │ + Queue Event Bus Observability + │ + Worker +``` + +而 Plugin 自身: + +```text +Plugin +├── Manifest +├── Resources +├── Actions +├── Skills +├── MCP +├── Workflows +├── Agent Profiles +├── UI +├── Settings +├── Widgets +├── Commands +├── Context Actions +├── Events +├── Migrations +├── Permissions +├── Dependencies +└── Configuration +``` + +最终实现: + +> **DevOS Core 负责平台,App 负责业务领域,Plugin 负责可复用能力,Agent 负责动态决策,而所有执行统一经过 Runtime。** + +这使 DevOS 真正成为一个可以持续扩展的 **Developer Work OS / Agent Platform**,而不是一个越来越臃肿的 Admin Dashboard。 \ No newline at end of file diff --git a/Docs/DevOS-Platform-v2/09_TASK_JOB_QUEUE_RUNTIME.md b/Docs/DevOS-Platform-v2/09_TASK_JOB_QUEUE_RUNTIME.md new file mode 100644 index 0000000..b506905 --- /dev/null +++ b/Docs/DevOS-Platform-v2/09_TASK_JOB_QUEUE_RUNTIME.md @@ -0,0 +1,4948 @@ +# 09_TASK_JOB_QUEUE_RUNTIME.md + +## DevOS Developer Work OS + +### Task / Job / Queue / Worker / Scheduler Runtime 设计规范 + +Version: 1.0 + +--- + +# 1. 文档目标 + +本文定义 DevOS 的统一异步执行基础设施: + +```text +Task +Job +Queue +Worker +Execution +Scheduler +Retry +Progress +Cancellation +Concurrency +``` + +核心目标: + +> **Agent、Plugin、Workflow、API、UI、CLI 都只能创建 Task / 调用 Action,不允许各自实现自己的任务队列和 Worker。** + +DevOS 最终应该形成唯一执行链: + +```text +User / Agent / Plugin / Workflow + ↓ + Task + ↓ + Job + ↓ + Queue + ↓ + Worker + ↓ + Action + ↓ + Action Runtime + ↓ + Execution + ↓ + Event +``` + +--- + +# 2. 为什么必须统一 Task Runtime + +例如用户: + +> 给我生成 100 篇文章。 + +错误实现: + +```text +Agent + ↓ +for 1..100 + ↓ +LLM + ↓ +API + ↓ +LLM + ↓ +API +``` + +这样会导致: + +* Agent 长时间占用 +* Token 浪费 +* 无法恢复 +* 无法暂停 +* 无法并发控制 +* 无法查看单项进度 +* 一个失败导致整个流程混乱 +* Agent 崩溃后任务消失 + +正确实现: + +```text +Agent + ↓ +Task + ├── Job 001 + ├── Job 002 + ├── Job 003 + ├── ... + └── Job 100 + ↓ + Queue + ↓ + Workers +``` + +Agent 只负责: + +```text +创建任务 +观察结果 +调整策略 +``` + +不负责: + +```text +Queue +Worker +Retry Loop +Concurrency +``` + +--- + +# 3. Task / Job / Execution 的区别 + +必须严格区分: + +```text +Task += 用户/Agent 要完成的一项工作 + +Job += Task 中可独立调度的一次工作单元 + +Execution += Action 实际执行的一次运行记录 +``` + +例如: + +```text +Task: +生成 100 篇 SEO 文章 + +Jobs: +article-001 +article-002 +... +article-100 + +Execution: +article-001.generate +article-002.generate +... +``` + +--- + +# 4. 核心边界 + +```text +Agent + ↓ +决定做什么 + ↓ +Task + ↓ +决定有哪些 Job + ↓ +Queue + ↓ +决定什么时候执行 + ↓ +Worker + ↓ +执行 Job + ↓ +Action Runtime + ↓ +产生 Execution +``` + +Golden Rule: + +> **Task 描述工作,Job 描述调度单位,Execution 描述实际执行。** + +--- + +# 5. Task + +Task 是用户可理解的业务工作单元。 + +例如: + +```text +SEO Audit +Generate Articles +Deploy Application +Sync GitHub +Backup Database +Import Products +``` + +定义: + +```ts +interface Task { + id: string; + + type: string; + + name: string; + + description?: string; + + status: TaskStatus; + + actor: ActorRef; + + organizationId: string; + + projectId?: string; + + input?: unknown; + + output?: unknown; + + progress: TaskProgress; + + priority: TaskPriority; + + createdAt: Date; + + startedAt?: Date; + + completedAt?: Date; + + metadata?: Record; +} +``` + +--- + +# 6. Task Status + +统一状态: + +```ts +type TaskStatus = + | "pending" + | "queued" + | "running" + | "paused" + | "waiting" + | "completed" + | "failed" + | "cancelled" + | "partially_completed"; +``` + +状态: + +```text +pending + ↓ +queued + ↓ +running + ↓ +completed +``` + +失败: + +```text +running + ↓ +failed +``` + +暂停: + +```text +running + ↓ +paused + ↓ +queued +``` + +取消: + +```text +pending / queued / running + ↓ + cancelled +``` + +--- + +# 7. Task 不等于 Job + +例如: + +```text +Task: +部署 myapp +``` + +可以包含: + +```text +Job 1: Build Docker Image +Job 2: Push Image +Job 3: Connect Server +Job 4: Deploy Container +Job 5: Health Check +``` + +因此: + +```text +1 Task ++ +N Jobs +``` + +--- + +# 8. Job + +Job 是 Queue 可以调度的最小工作单元。 + +```ts +interface Job { + id: string; + + taskId: string; + + type: string; + + actionId: string; + + input: unknown; + + status: JobStatus; + + priority: number; + + attempts: number; + + maxAttempts: number; + + scheduledAt?: Date; + + startedAt?: Date; + + completedAt?: Date; + + workerId?: string; + + executionId?: string; + + dependencies?: string[]; + + metadata?: Record; +} +``` + +--- + +# 9. Job Status + +```ts +type JobStatus = + | "pending" + | "queued" + | "leased" + | "running" + | "retrying" + | "completed" + | "failed" + | "cancelled"; +``` + +完整流程: + +```text +pending + ↓ +queued + ↓ +leased + ↓ +running + ↓ +completed +``` + +失败: + +```text +running + ↓ +retrying + ↓ +queued +``` + +最终: + +```text +failed +``` + +--- + +# 10. Execution + +Execution 是 Action Runtime 的实际执行记录。 + +例如: + +```text +Job: +github.repository.sync + +Execution: +exec_123456 +``` + +定义: + +```ts +interface Execution { + id: string; + + jobId?: string; + + actionId: string; + + actor: ActorRef; + + status: ExecutionStatus; + + input?: unknown; + + output?: unknown; + + error?: ExecutionError; + + startedAt?: Date; + + completedAt?: Date; + + durationMs?: number; + + metadata?: Record; +} +``` + +--- + +# 11. 三者关系 + +```text +Task + │ + ├── Job + │ └── Execution + │ + ├── Job + │ └── Execution + │ + └── Job + └── Execution +``` + +一个 Job 在重试时: + +```text +Job + ├── Execution #1 → failed + ├── Execution #2 → failed + └── Execution #3 → completed +``` + +因此: + +> Job 是逻辑工作,Execution 是尝试。 + +--- + +# 12. 为什么 Retry 不能创建新 Task + +错误: + +```text +Task A + ↓ +failed + ↓ +Task B +``` + +正确: + +```text +Task A + ↓ +Job A + ├── Execution 1 failed + ├── Execution 2 failed + └── Execution 3 completed +``` + +这样整个任务的历史保持完整。 + +--- + +# 13. Queue + +Queue 是 Job 的调度层。 + +```ts +interface JobQueue { + enqueue(job: Job): Promise; + + dequeue(queueName: string): Promise; + + acknowledge(jobId: string): Promise; + + retry(jobId: string, delayMs: number): Promise; + + cancel(jobId: string): Promise; +} +``` + +--- + +# 14. Queue 不执行业务逻辑 + +Queue 只负责: + +```text +保存 +排序 +等待 +分发 +重试调度 +``` + +不能: + +```text +Queue + ↓ +GitHub API +``` + +必须: + +```text +Queue + ↓ +Worker + ↓ +Action Runtime +``` + +--- + +# 15. Queue 类型 + +推荐至少: + +```text +default +high +low +ai +network +browser +deployment +sync +``` + +但不要过度创建 Queue。 + +可以通过: + +```text +priority +concurrency +resource group +``` + +实现细粒度调度。 + +--- + +# 16. Queue Priority + +定义: + +```ts +type TaskPriority = + | "critical" + | "high" + | "normal" + | "low"; +``` + +内部转换: + +```text +critical → 100 +high → 75 +normal → 50 +low → 25 +``` + +Worker 优先执行高优先级 Job。 + +--- + +# 17. Worker + +Worker 是真正执行 Job 的进程。 + +```ts +interface Worker { + id: string; + + name: string; + + queues: string[]; + + status: WorkerStatus; + + concurrency: number; + + capabilities?: string[]; + + startedAt: Date; + + lastHeartbeatAt?: Date; +} +``` + +--- + +# 18. Worker Status + +```text +starting +idle +busy +draining +stopped +unhealthy +``` + +--- + +# 19. Worker 不应该拥有业务状态 + +Worker 不应该保存: + +```text +Task state +User state +Agent state +Plugin state +``` + +Worker 只负责: + +```text +receive Job +execute +report +``` + +这样 Worker 可以随时: + +```text +restart +scale +replace +``` + +--- + +# 20. Worker 执行流程 + +```text +Worker + ↓ +Receive Job + ↓ +Acquire Lease + ↓ +Validate Job + ↓ +Create Execution + ↓ +Action Runtime + ↓ +Report Progress + ↓ +Complete Execution + ↓ +Update Job + ↓ +Update Task + ↓ +Publish Event +``` + +--- + +# 21. Lease + +Worker 获取 Job 时必须建立 Lease。 + +例如: + +```text +Job: +abc + +Lease: +worker-03 + +Expires: +22:31:00 +``` + +防止: + +```text +Worker A + ↓ +Job + +Worker A crash + +Worker B + ↓ +same Job +``` + +导致重复执行。 + +--- + +# 22. Lease Timeout + +如果 Worker 心跳消失: + +```text +Lease expired +``` + +Job: + +```text +leased +``` + +重新变成: + +```text +queued +``` + +然后其他 Worker 可以领取。 + +--- + +# 23. Heartbeat + +Worker: + +```text +每 5 秒 +``` + +发送: + +```text +heartbeat +``` + +例如: + +```ts +interface WorkerHeartbeat { + workerId: string; + + timestamp: Date; + + activeJobs: number; + + capacity: number; +} +``` + +--- + +# 24. Worker Graceful Shutdown + +Worker 停止时: + +```text +SIGTERM + ↓ +draining + ↓ +停止接收新 Job + ↓ +等待当前 Job + ↓ +完成 + ↓ +stopped +``` + +如果超时: + +```text +release leases +``` + +让其他 Worker 接管。 + +--- + +# 25. Worker Concurrency + +例如: + +```text +Worker A +concurrency = 5 +``` + +最多: + +```text +5 Jobs +``` + +同时执行。 + +不同 Worker: + +```text +Worker A → 5 +Worker B → 5 +Worker C → 10 +``` + +总并发: + +```text +20 +``` + +--- + +# 26. Resource Concurrency + +除了 Worker,还需要限制外部资源。 + +例如: + +```text +OpenAI +maxConcurrency = 10 + +GitHub +maxConcurrency = 20 + +Browser +maxConcurrency = 5 +``` + +否则: + +```text +100 Jobs + ↓ +100 requests + ↓ +API rate limit +``` + +--- + +# 27. Resource Group + +Job 可以声明: + +```ts +resourceGroup?: string; +``` + +例如: + +```text +ai.openai +github.api +browser.instance +server.production +``` + +Scheduler / Queue Runtime 可以保证: + +```text +同一 resourceGroup +最多 N 个并发 +``` + +--- + +# 28. Concurrency Policy + +```ts +interface ConcurrencyPolicy { + key: string; + + maxConcurrent: number; + + scope: + | "global" + | "organization" + | "project" + | "resource"; +} +``` + +例如: + +```text +OpenAI +Global: +100 + +Organization: +10 + +Project: +5 +``` + +--- + +# 29. Task Progress + +Task 必须支持统一进度: + +```ts +interface TaskProgress { + total?: number; + + completed: number; + + failed: number; + + running: number; + + percentage?: number; + + message?: string; + + updatedAt: Date; +} +``` + +例如: + +```text +SEO Article Generation + +72 / 100 +72% +``` + +--- + +# 30. Job Progress + +Job 也可以报告: + +```text +0% +25% +50% +75% +100% +``` + +例如: + +```text +Download website +``` + +Worker: + +```text +25% +50% +75% +100% +``` + +Task Runtime 汇总。 + +--- + +# 31. Progress Event + +统一事件: + +```text +task.progress +job.progress +``` + +例如: + +```ts +{ + type: "job.progress", + jobId: "job_123", + percentage: 75 +} +``` + +前端通过: + +```text +WebSocket +SSE +Polling +``` + +获取。 + +--- + +# 32. Cancellation + +Task 必须支持: + +```text +Cancel +``` + +但: + +```text +Cancel +≠ +kill process +``` + +流程: + +```text +User + ↓ +Cancel Task + ↓ +Task Runtime + ↓ +Signal Job + ↓ +AbortSignal + ↓ +Action Runtime + ↓ +Plugin +``` + +--- + +# 33. AbortSignal + +ActionContext 已经定义: + +```ts +signal: AbortSignal; +``` + +Worker 必须传递: + +```text +Task + ↓ +Job + ↓ +Execution + ↓ +ActionContext.signal +``` + +Plugin / Action 必须响应取消。 + +--- + +# 34. Cancellation State + +推荐: + +```text +pending → cancelled +queued → cancelled +running → cancelling → cancelled +``` + +增加: + +```ts +"cancelling" +``` + +可以避免误认为 Action 已立即停止。 + +--- + +# 35. 强制终止 + +如果 Action 长时间不响应: + +```text +Grace Period + ↓ +Force Termination +``` + +但只能由: + +```text +Worker Runtime +``` + +执行。 + +不能由 UI 直接杀 Worker。 + +--- + +# 36. Retry + +Job 可以定义: + +```ts +interface RetryPolicy { + maxAttempts: number; + + backoff: + | "fixed" + | "linear" + | "exponential"; + + initialDelayMs: number; + + maxDelayMs?: number; + + jitter?: boolean; +} +``` + +--- + +# 37. Retry Example + +```text +Attempt 1 + ↓ +fail + ↓ +1 sec + ↓ +Attempt 2 + ↓ +fail + ↓ +2 sec + ↓ +Attempt 3 + ↓ +fail + ↓ +4 sec + ↓ +Attempt 4 +``` + +--- + +# 38. Retryable Error + +Action Error 必须声明: + +```ts +interface ExecutionError { + code: string; + + message: string; + + retryable: boolean; + + category?: string; + + details?: unknown; +} +``` + +例如: + +```text +HTTP 429 +retryable = true +``` + +而: + +```text +INVALID_INPUT +retryable = false +``` + +--- + +# 39. Retry 分类 + +推荐: + +```text +network +timeout +rate_limit +temporary +dependency +authentication +authorization +validation +business +system +``` + +默认策略: + +```text +network → retry +timeout → retry +rate_limit → retry +temporary → retry + +validation → no retry +authorization → no retry +invalid_input → no retry +``` + +--- + +# 40. Dead Letter Queue + +最终失败的 Job: + +```text +Retry exhausted + ↓ +Dead Letter Queue +``` + +例如: + +```text +DLQ +├── job-123 +├── job-456 +└── job-789 +``` + +管理员可以: + +```text +Retry +Inspect +Cancel +Replay +``` + +--- + +# 41. Replay + +Replay 必须生成新的 Execution。 + +不能修改旧 Execution。 + +例如: + +```text +Job + ├── Execution 1 failed + ├── Execution 2 failed + └── Execution 3 ← replay +``` + +Audit 保留完整历史。 + +--- + +# 42. Idempotency + +所有可能重试的 Action 必须考虑幂等。 + +例如: + +```text +createRepository +``` + +第一次: + +```text +GitHub 创建成功 +``` + +但 Worker 在收到响应前崩溃。 + +系统认为: + +```text +failed +``` + +再次执行可能产生: + +```text +duplicate repository +``` + +所以必须支持: + +```text +idempotencyKey +``` + +--- + +# 43. Job Idempotency + +```ts +interface Job { + idempotencyKey?: string; +} +``` + +Action Runtime: + +```text +same key + ↓ +same logical operation +``` + +如果已经成功: + +```text +return existing result +``` + +--- + +# 44. Task Idempotency + +用户重复点击: + +```text +Generate 100 articles +``` + +不能创建: + +```text +Task A +Task B +Task C +``` + +除非用户明确要求。 + +可以使用: + +```text +taskType +organization +project +idempotencyKey +``` + +进行去重。 + +--- + +# 45. Scheduling + +Scheduler 负责: + +```text +什么时候创建 Task / Job +``` + +例如: + +```text +Every 10 minutes +Daily +Weekly +At specific time +After event +``` + +Scheduler 不负责执行。 + +--- + +# 46. Scheduler Architecture + +```text +Scheduler + ↓ +Detect Trigger + ↓ +Create Task / Job + ↓ +Queue + ↓ +Worker +``` + +--- + +# 47. Cron + +支持: + +```text +0 * * * * +0 0 * * * +0 0 * * 1 +``` + +例如: + +```text +每小时同步 GitHub +``` + +Scheduler: + +```text +cron + ↓ +github.repository.sync Task +``` + +--- + +# 48. Schedule Resource + +Schedule 本身也是 Resource: + +```text +scheduler.schedule +``` + +Action: + +```text +scheduler.schedule.create +scheduler.schedule.update +scheduler.schedule.delete +scheduler.schedule.enable +scheduler.schedule.disable +``` + +这样 UI / API / Agent 都统一。 + +--- + +# 49. Schedule Definition + +```ts +interface Schedule { + id: string; + + name: string; + + cron: string; + + timezone: string; + + actionId?: string; + + taskType?: string; + + input?: unknown; + + enabled: boolean; + + organizationId: string; + + projectId?: string; + + nextRunAt?: Date; + + lastRunAt?: Date; +} +``` + +--- + +# 50. Timezone + +Schedule 必须明确: + +```text +timezone +``` + +不能默认: + +```text +server timezone +``` + +例如: + +```text +Asia/Tokyo +UTC +America/New_York +``` + +--- + +# 51. Missed Schedule + +服务器停机: + +```text +00:00 schedule +``` + +但服务器: + +```text +23:00 - 02:00 +offline +``` + +重启后怎么办必须由策略决定: + +```text +skip +run_once +run_all +``` + +默认: + +```text +skip +``` + +避免突然创建大量任务。 + +--- + +# 52. Event Trigger + +Task 也可以由 Event 创建。 + +例如: + +```text +github.pull_request.created +``` + +触发: + +```text +code review Task +``` + +流程: + +```text +Event + ↓ +Trigger + ↓ +Task + ↓ +Job + ↓ +Queue +``` + +--- + +# 53. Webhook Trigger + +例如: + +```text +GitHub Webhook + ↓ +DevOS Event + ↓ +Task +``` + +Webhook Controller 只负责: + +```text +receive +verify +publish event +``` + +不负责业务执行。 + +--- + +# 54. Task Dependencies + +Task 可以依赖其他 Task: + +```text +Build + ↓ +Deploy + ↓ +Health Check +``` + +Job 也可以依赖 Job: + +```text +Job A + ↓ +Job B + ↓ +Job C +``` + +--- + +# 55. Job Dependency Graph + +定义: + +```ts +interface JobDependency { + jobId: string; + + dependsOn: string[]; + + condition?: + | "all" + | "any" + | "success" + | "completed"; +} +``` + +--- + +# 56. DAG + +推荐使用 DAG: + +```text + Build + / \ + Test Security Scan + \ / + Deploy + ↓ + Health Check +``` + +不能出现: + +```text +A → B +B → C +C → A +``` + +必须检测循环。 + +--- + +# 57. Parallel Jobs + +例如: + +```text +Build + ↓ +├── Test +├── Security Scan +└── Lint +``` + +三者可以并发。 + +完成后: + +```text +Test +Security +Lint + ↓ +Deploy +``` + +--- + +# 58. Task Aggregation + +Task 状态由 Jobs 聚合: + +```text +100 jobs +``` + +如果: + +```text +90 completed +5 failed +5 running +``` + +Task: + +```text +partially_completed +``` + +进度: + +```text +90% +``` + +--- + +# 59. Task Completion Policy + +支持: + +```text +all_success +best_effort +any_success +threshold +``` + +例如: + +```text +100 articles +``` + +要求: + +```text +至少 95 篇成功 +``` + +则: + +```text +threshold = 95% +``` + +--- + +# 60. Batch Task + +针对大量工作: + +```text +Task + ↓ +Batch + ↓ +Jobs +``` + +例如: + +```text +生成 1000 篇文章 +``` + +不要: + +```text +1000 个 Agent Run +``` + +应该: + +```text +1 Agent Goal + ↓ +1 Task + ↓ +1000 Jobs +``` + +--- + +# 61. Batch Job Generation + +Agent 可以告诉 Task Runtime: + +```ts +createBatchTask({ + type: "content.generate", + items: articles +}); +``` + +Task Runtime: + +```text +items + ↓ +Job Factory + ↓ +Jobs +``` + +Agent 不负责逐个创建。 + +--- + +# 62. Job Factory + +```ts +interface JobFactory { + createJobs( + task: Task, + input: unknown + ): Promise; +} +``` + +例如: + +```text +100 URLs + ↓ +100 Jobs +``` + +--- + +# 63. Dynamic Job Creation + +有些 Task 不知道最终 Job 数量。 + +例如: + +```text +爬取网站 +``` + +流程: + +```text +Job 1: +Discover URLs + + ↓ + +发现 500 URLs + + ↓ + +创建 500 Jobs +``` + +允许 Worker / Action 发布: + +```text +Task Expansion +``` + +但必须通过: + +```text +Task Runtime +``` + +完成。 + +--- + +# 64. Dynamic Expansion 限制 + +必须设置: + +```text +maxJobs +maxDepth +maxExpansion +``` + +防止: + +```text +Job + ↓ +100 jobs + ↓ +10000 jobs + ↓ +1,000,000 jobs +``` + +--- + +# 65. Backpressure + +当 Queue: + +```text +100000 jobs +``` + +不能继续无限创建。 + +Task Runtime 应返回: + +```text +accepted +queued +throttled +``` + +例如: + +```text +Queue capacity exceeded +``` + +进入: + +```text +waiting +``` + +--- + +# 66. Rate Limiting + +Job 可以受: + +```text +Global Rate Limit +Organization Rate Limit +Project Rate Limit +Plugin Rate Limit +External API Rate Limit +``` + +共同约束。 + +--- + +# 67. Token Budget + +AI Job 可以声明: + +```ts +interface JobBudget { + maxTokens?: number; + + maxCost?: number; + + maxDurationMs?: number; +} +``` + +例如: + +```text +Generate Article +maxTokens = 10000 +maxCost = $0.10 +``` + +超过: + +```text +budget exceeded +``` + +Job 失败或进入审批。 + +--- + +# 68. Cost Tracking + +每次 Execution 记录: + +```text +inputTokens +outputTokens +totalTokens +estimatedCost +actualCost +currency +``` + +Task 汇总: + +```text +100 articles +Total tokens: 2.4M +Cost: $13.20 +``` + +--- + +# 69. External API Usage + +Execution 可以记录: + +```text +externalRequests +externalDuration +externalCost +``` + +例如: + +```text +OpenAI: +10 requests + +GitHub: +5 requests + +Browser: +3 sessions +``` + +用于: + +```text +Observability +Billing +Budget +``` + +--- + +# 70. Task Events + +至少: + +```text +task.created +task.queued +task.started +task.progress +task.paused +task.resumed +task.completed +task.failed +task.cancelled +``` + +Job: + +```text +job.created +job.queued +job.started +job.retrying +job.completed +job.failed +job.cancelled +``` + +--- + +# 71. Task Audit + +例如: + +```text +User created Task +Agent modified Task +Worker started Job +Action executed +Job retried +User cancelled Task +``` + +都进入: + +```text +Audit Runtime +``` + +--- + +# 72. Task API + +推荐: + +```text +GET /api/tasks +GET /api/tasks/:id + +POST /api/tasks + +POST /api/tasks/:id/pause +POST /api/tasks/:id/resume +POST /api/tasks/:id/cancel +POST /api/tasks/:id/retry + +GET /api/tasks/:id/jobs +GET /api/tasks/:id/executions +GET /api/tasks/:id/events +``` + +--- + +# 73. Job API + +```text +GET /api/jobs + +GET /api/jobs/:id + +POST /api/jobs/:id/retry + +POST /api/jobs/:id/cancel + +GET /api/jobs/:id/executions +``` + +普通用户通常不需要直接操作 Job。 + +Job API 主要服务: + +```text +Admin +Developer +Operations +Agent Runtime +``` + +--- + +# 74. Worker API + +Worker 通常使用内部协议: + +```text +POST /internal/workers/register +POST /internal/workers/heartbeat +POST /internal/workers/lease +POST /internal/workers/report +``` + +也可以使用 Redis / Message Queue。 + +--- + +# 75. Queue Backend + +第一版本可以使用: + +```text +Redis +``` + +实现: + +```text +Queue +Lease +Retry +Delay +Priority +``` + +数据库负责: + +```text +Task +Job +Execution +Audit +``` + +Redis 负责: + +```text +Scheduling +Queue +Locks +Heartbeat +``` + +--- + +# 76. Database 与 Queue 分工 + +不要把 Redis 当永久业务数据库。 + +推荐: + +```text +PostgreSQL +├── Task +├── Job +├── Execution +├── Schedule +└── Audit + +Redis +├── Queue +├── Lease +├── Lock +├── Worker heartbeat +└── Temporary state +``` + +--- + +# 77. Queue Consistency + +关键问题: + +```text +DB Job created + ↓ +Redis enqueue failed +``` + +如果直接: + +```text +DB commit +Redis enqueue +``` + +可能造成 Job 永远不执行。 + +因此必须支持: + +```text +Outbox Pattern +``` + +--- + +# 78. Outbox + +流程: + +```text +DB Transaction + ├── Create Job + └── Create Outbox Event + ↓ + Commit + ↓ + Outbox Worker + ↓ + Redis Queue +``` + +这样可以保证最终进入 Queue。 + +--- + +# 79. Event Outbox + +同样: + +```text +Action Execution + ↓ +DB transaction + ├── update execution + └── event outbox +``` + +再: + +```text +Outbox + ↓ +Event Bus +``` + +避免: + +```text +DB 成功 +Event 丢失 +``` + +--- + +# 80. Queue At-Least-Once + +默认: + +```text +At-least-once delivery +``` + +意味着: + +```text +Job 可能被执行超过一次 +``` + +所以: + +> Action 必须尽可能幂等。 + +不要假设: + +```text +exactly-once +``` + +--- + +# 81. Duplicate Detection + +Worker 获取 Job: + +```text +jobId +``` + +Action Runtime 检查: + +```text +execution +idempotency +``` + +如果已经完成: + +```text +return existing execution +``` + +--- + +# 82. Distributed Lock + +某些 Action 必须: + +```text +single execution +``` + +例如: + +```text +production deployment +``` + +使用: + +```text +Lock: +deployment:production:app +``` + +确保: + +```text +只有一个 Job +``` + +执行。 + +--- + +# 83. Task Lock + +Task 也可以: + +```text +exclusive +``` + +例如: + +```text +Database Migration +``` + +禁止同时执行: + +```text +Migration A +Migration B +``` + +--- + +# 84. Pause + +Pause Task: + +```text +Task + ↓ +paused +``` + +行为: + +```text +queued jobs +→ 不再领取 + +running jobs +→ 默认继续完成 + +new jobs +→ 不创建/不调度 +``` + +也可以提供: + +```text +hard pause +``` + +请求取消正在运行的 Job。 + +--- + +# 85. Resume + +```text +paused + ↓ +resume + ↓ +queued +``` + +继续剩余 Jobs。 + +已经完成的 Job: + +```text +不重复执行 +``` + +--- + +# 86. Task Timeout + +Task 可以定义: + +```text +maxDurationMs +``` + +例如: + +```text +2 hours +``` + +超过: + +```text +Task timeout +``` + +策略: + +```text +cancel remaining jobs +``` + +--- + +# 87. Job Timeout + +每个 Job 可以定义: + +```text +timeoutMs +``` + +例如: + +```text +browser.navigate +30 sec +``` + +超时: + +```text +Execution timeout + ↓ +Abort + ↓ +Retry +``` + +如果 retryable。 + +--- + +# 88. Queue Timeout + +如果 Job: + +```text +queued +``` + +超过: + +```text +maxQueueWait +``` + +可以: + +```text +fail +``` + +或者: + +```text +priority escalate +``` + +用于检测 Worker 不足。 + +--- + +# 89. Worker Auto Scaling + +未来可以: + +```text +Queue Depth + ↓ +Scaler + ↓ +Worker Count +``` + +例如: + +```text +Queue: +1000 Jobs + +Workers: +5 + +Scale: +20 +``` + +但第一版本不需要复杂 Kubernetes Autoscaler。 + +保留接口: + +```ts +interface WorkerScaler {} +``` + +--- + +# 90. Worker Capability + +某些 Job 只能给特定 Worker。 + +例如: + +```text +browser Job +``` + +要求: + +```text +worker.capabilities: +browser +``` + +Server deployment: + +```text +worker.capabilities: +docker +ssh +``` + +--- + +# 91. Worker Tags + +Worker: + +```text +tags: +browser +linux +gpu +region-us +``` + +Job: + +```text +requiredTags: +browser +``` + +Scheduler: + +```text +只分配给匹配 Worker +``` + +--- + +# 92. Plugin Job + +Plugin 可以声明 Job 类型: + +```text +github.sync +browser.crawl +cloudflare.dns.update +``` + +但执行: + +```text +Job + ↓ +Action Runtime +``` + +Plugin 不拥有 Worker Runtime。 + +--- + +# 93. Agent Task + +Agent 创建: + +```text +Task +``` + +例如: + +```text +Goal: +检查 100 个网站 SEO + +Task: +seo.batch_audit + +Jobs: +site-001 +... +site-100 +``` + +Agent: + +```text +观察 + ↓ +等待 Task + ↓ +分析结果 +``` + +而不是: + +```text +Agent + ↓ +100 次工具调用 +``` + +--- + +# 94. Agent Observation + +Task 完成后产生: + +```text +task.completed +``` + +Agent 收到: + +```text +Observation +``` + +然后决定: + +```text +Complete +Replan +Create another Task +Ask Human +``` + +--- + +# 95. Agent 与 Task 的边界 + +```text +Agent: +Why / What next + +Task: +Work to be done + +Job: +Unit to schedule + +Worker: +Who executes + +Action: +How to execute + +Execution: +What happened +``` + +这是整个 DevOS 最重要的边界之一。 + +--- + +# 96. Workflow 与 Task + +Workflow: + +```text +预定义流程 +``` + +Task: + +```text +一次实际工作 +``` + +例如: + +```text +Workflow: +SEO Audit Workflow + +Task: +Audit example.com +``` + +执行: + +```text +Workflow + ↓ +Task + ↓ +Jobs +``` + +--- + +# 97. Workflow 不应该绕过 Task + +错误: + +```text +Workflow + ↓ +Action + ↓ +Action + ↓ +Action +``` + +如果流程可能: + +* 长时间运行 +* 可暂停 +* 可重试 +* 可观察 + +应该: + +```text +Workflow + ↓ +Task + ↓ +Jobs +``` + +--- + +# 98. Task UI + +推荐: + +```text +/tasks +``` + +列表: + +```text +Task Status Progress + +SEO Audit Running 72% + +Generate Articles Completed 100% + +Deploy App Failed 80% + +GitHub Sync Queued 0% +``` + +--- + +# 99. Task Detail + +```text +SEO Audit +──────────────────── + +Status: +Running + +Progress: +72% + +Jobs: +72 completed +3 failed +5 running +20 queued + +Started: +10:30 + +Duration: +12m + +Cost: +$2.31 +``` + +--- + +# 100. Task Timeline + +显示: + +```text +10:30 Task created +10:31 Job 001 started +10:31 Job 001 completed +10:32 Job 002 started +10:33 Job 002 retrying +10:34 Job 002 completed +... +``` + +数据来自: + +```text +Event +Execution +Audit +``` + +不是 UI 自己记录。 + +--- + +# 101. Job Detail + +```text +Job +──────────────── + +Action: +seo.website.scan + +Status: +Completed + +Attempts: +2 + +Execution: +exec_123 + +Worker: +worker-07 + +Duration: +31s + +Retry: +1 +``` + +--- + +# 102. Execution Detail + +```text +Execution +──────────────── + +Action: +seo.website.scan + +Actor: +agent:seo-agent + +Input: +example.com + +Output: +... + +Duration: +13.2s + +External Requests: +4 + +Tokens: +0 + +Cost: +$0.00 +``` + +--- + +# 103. Task Streaming + +对于实时任务: + +```text +Task + ↓ +SSE / WebSocket + ↓ +UI +``` + +推送: + +```text +progress +logs +job status +execution output +events +``` + +--- + +# 104. Task Logs + +统一: + +```text +Task + ↓ +Job + ↓ +Execution + ↓ +Logs +``` + +日志必须关联: + +```text +taskId +jobId +executionId +workerId +pluginId +actionId +``` + +--- + +# 105. Task Output + +Task 可以最终产生: + +```ts +interface TaskOutput { + summary?: string; + + data?: unknown; + + artifacts?: ArtifactRef[]; + + links?: LinkRef[]; +} +``` + +例如: + +```text +100 SEO reports +``` + +生成: + +```text +reports/*.json +reports/*.html +``` + +通过: + +```text +Artifact Runtime +``` + +管理。 + +--- + +# 106. Artifact + +不要直接把巨大结果塞进: + +```text +Task.output +``` + +例如: + +```text +1000 MB CSV +``` + +应该: + +```text +Task + ↓ +Artifact + ↓ +Object Storage +``` + +Task 只保存: + +```text +artifactId +``` + +--- + +# 107. Task Result Size + +推荐: + +```text +small output +→ DB + +large output +→ Artifact Storage +``` + +例如: + +```text +JSON < 1MB +→ DB + +large HTML +→ Object Storage +``` + +具体阈值配置化。 + +--- + +# 108. Task Security + +Task 必须带: + +```text +actor +organizationId +projectId +``` + +查询 Task: + +```text +User A +``` + +不能读取: + +```text +Organization B +``` + +--- + +# 109. Task Authorization + +前端: + +```text +显示/隐藏 +``` + +只是 UX。 + +真正: + +```text +GET /tasks/:id +POST /tasks/:id/cancel +``` + +必须经过: + +```text +Authorization +Resource Scope +``` + +--- + +# 110. Task Audit + +Cancel: + +```text +User + ↓ +task.cancel + ↓ +Task Runtime +``` + +Audit: + +```text +actor=user +action=task.cancel +resource=task:123 +``` + +--- + +# 111. Task API 不直接执行 Action + +错误: + +```text +POST /tasks + ↓ +Controller + ↓ +executeAction() +``` + +正确: + +```text +POST /tasks + ↓ +Task Runtime + ↓ +Create Task + ↓ +Create Job + ↓ +Queue +``` + +Worker 才执行 Action。 + +--- + +# 112. Action Runtime 与 Worker + +Worker 不应该自己实现 Action。 + +正确: + +```text +Worker + ↓ +ActionRuntime.execute(actionId, input, context) +``` + +Action Runtime 负责: + +```text +Permission +Validation +Middleware +Transaction +Audit +Execution +Error +``` + +--- + +# 113. Worker 与 Plugin + +Worker: + +```text +不需要知道 GitHub Plugin 的内部实现 +``` + +只需要: + +```text +Action ID +``` + +例如: + +```text +github.repository.sync +``` + +Action Registry: + +```text +resolve +``` + +然后执行。 + +--- + +# 114. Queue 与 Plugin + +Queue 不知道: + +```text +GitHub +SEO +Browser +``` + +Queue 只知道: + +```text +Job +priority +resourceGroup +schedule +``` + +--- + +# 115. Scheduler 与 Agent + +Scheduler 可以触发: + +```text +Agent Goal +``` + +例如: + +```text +Every Monday + ↓ +Create Agent Goal: +分析本周 SEO 数据 +``` + +Agent 再: + +```text +Goal + ↓ +Plan + ↓ +Task +``` + +因此: + +```text +Scheduler + ≠ +Agent +``` + +--- + +# 116. Scheduler 与 Plugin + +Plugin 可以声明 Schedule: + +```text +GitHub Plugin + ↓ +github.sync schedule +``` + +Scheduler 统一执行。 + +Plugin 不实现 Cron Worker。 + +--- + +# 117. Queue Worker Architecture + +推荐: + +```text +packages/task/ +├── task-runtime.ts +├── task-service.ts +├── task-progress.ts +├── task-cancellation.ts +│ +├── job-runtime.ts +├── job-service.ts +├── job-factory.ts +│ +├── queue/ +│ ├── queue.ts +│ ├── redis-queue.ts +│ └── queue-scheduler.ts +│ +├── worker/ +│ ├── worker.ts +│ ├── worker-manager.ts +│ ├── worker-heartbeat.ts +│ └── worker-lease.ts +│ +├── retry/ +│ └── retry-policy.ts +│ +├── scheduler/ +│ ├── scheduler.ts +│ ├── cron.ts +│ └── triggers.ts +│ +└── execution/ + └── execution-service.ts +``` + +--- + +# 118. Database Models + +至少: + +```text +Task +Job +Execution +Schedule +Worker +JobDependency +TaskEvent +OutboxEvent +``` + +可选: + +```text +TaskArtifact +TaskLog +JobLease +``` + +--- + +# 119. Task Repository + +```ts +interface TaskRepository { + create(input): Promise; + + findById(id): Promise; + + updateStatus(id, status): Promise; + + updateProgress(id, progress): Promise; + + list(filter): Promise; +} +``` + +--- + +# 120. Job Repository + +```ts +interface JobRepository { + create(input): Promise; + + findById(id): Promise; + + claim(id, workerId): Promise; + + updateStatus(id, status): Promise; + + incrementAttempts(id): Promise; + + listByTask(taskId): Promise; +} +``` + +--- + +# 121. Worker Manager + +```ts +interface WorkerManager { + register(worker): Promise; + + heartbeat(workerId): Promise; + + drain(workerId): Promise; + + stop(workerId): Promise; + + list(): Promise; +} +``` + +--- + +# 122. Queue Adapter + +不要把 Redis API 直接暴露给业务。 + +定义: + +```ts +interface QueueAdapter { + enqueue(job: QueueMessage): Promise; + + reserve( + queue: string, + workerId: string + ): Promise; + + ack(messageId: string): Promise; + + release(messageId: string): Promise; + + delay(messageId: string, delayMs: number): Promise; +} +``` + +未来可以替换: + +```text +Redis +RabbitMQ +Kafka +SQS +NATS +``` + +而不修改 Task Runtime。 + +--- + +# 123. 第一版本 Queue + +第一版本推荐: + +```text +PostgreSQL ++ +Redis +``` + +不要一开始引入: + +```text +Kafka +RabbitMQ +Kubernetes +Temporal +``` + +除非实际规模已经需要。 + +架构层保留: + +```text +QueueAdapter +``` + +未来可以替换。 + +--- + +# 124. Transaction Boundary + +创建 Task: + +```text +BEGIN + ↓ +Task + ↓ +Jobs + ↓ +Outbox + ↓ +COMMIT +``` + +Queue: + +```text +Outbox + ↓ +Redis +``` + +不要: + +```text +Redis enqueue + ↓ +DB transaction +``` + +否则容易产生孤儿 Job。 + +--- + +# 125. Worker Crash Recovery + +场景: + +```text +Worker + ↓ +Job + ↓ +Action executing + ↓ +Worker crash +``` + +Lease: + +```text +expired +``` + +系统: + +```text +Job + ↓ +queued + ↓ +Worker B +``` + +然后: + +```text +new Execution +``` + +--- + +# 126. Zombie Worker + +Worker 失去网络但仍运行: + +```text +Worker A +``` + +如果 Lease 已过期: + +```text +Worker B +``` + +领取 Job。 + +可能产生: + +```text +A + B +``` + +同时执行。 + +因此: + +> 所有有副作用的 Action 必须使用 Idempotency / Distributed Lock。 + +--- + +# 127. Exactly Once 不作为基础假设 + +DevOS 默认: + +```text +at-least-once +``` + +开发者必须: + +```text +设计幂等 +``` + +而不是依赖: + +```text +exactly-once +``` + +--- + +# 128. Task Retry 与 Agent Replan + +两者完全不同。 + +```text +Retry += +相同 Job 再执行 + +Replan += +Agent 改变解决方案 +``` + +例如: + +```text +Browser API timeout +``` + +→ Retry。 + +而: + +```text +网站无法访问 +``` + +Agent 判断: + +```text +改用 Search Plugin +``` + +→ Replan。 + +--- + +# 129. Task Failure 与 Agent Failure + +Task: + +```text +failed +``` + +Agent 不一定: + +```text +failed +``` + +Agent 可以: + +```text +Observe + ↓ +Replan + ↓ +Create new Task +``` + +例如: + +```text +SEO Audit Task + ↓ +failed + ↓ +Agent: +尝试 Browser Plugin +``` + +--- + +# 130. Task Approval + +危险 Task 可以: + +```text +waiting +``` + +等待: + +```text +Approval +``` + +例如: + +```text +Production Deployment +``` + +流程: + +```text +Agent + ↓ +Task + ↓ +Approval + ↓ +waiting + ↓ +Human approve + ↓ +queued + ↓ +Worker +``` + +--- + +# 131. Approval 不应该是 Worker 逻辑 + +Worker 遇到: + +```text +requiresApproval +``` + +不能自己: + +```text +ask user +``` + +而应该: + +```text +Task Runtime + ↓ +Approval Resource +``` + +--- + +# 132. Task Budget + +Task 可以定义: + +```ts +interface TaskBudget { + maxJobs?: number; + + maxDurationMs?: number; + + maxCost?: number; + + maxTokens?: number; + + maxExternalRequests?: number; +} +``` + +超过预算: + +```text +budget_exceeded +``` + +--- + +# 133. Budget Aggregation + +例如: + +```text +Task: +100 articles + +Budget: +$20 +``` + +Jobs: + +```text +$0.10 +$0.15 +$0.08 +... +``` + +Task Runtime 汇总: + +```text +actualCost +``` + +超过: + +```text +pause +cancel +fail +approval +``` + +策略可配置。 + +--- + +# 134. Task Resource Limits + +可以限制: + +```text +maxJobs +maxConcurrency +maxRetries +maxExecutionTime +maxQueueTime +maxCost +``` + +防止异常 Agent 产生: + +```text +1000000 Jobs +``` + +--- + +# 135. Task Observability + +每个 Task 必须可以追踪: + +```text +Task ID +Job IDs +Execution IDs +Worker IDs +Action IDs +Plugin IDs +Events +Logs +Costs +Retries +``` + +形成完整 Trace: + +```text +Goal + ↓ +Task + ↓ +Job + ↓ +Execution + ↓ +Action + ↓ +Plugin + ↓ +External API +``` + +--- + +# 136. Task Trace ID + +建议: + +```text +traceId +``` + +贯穿: + +```text +Agent +Task +Job +Execution +Action +Plugin +External Request +``` + +这样一次用户请求可以完整追踪。 + +--- + +# 137. Task Metrics + +至少: + +```text +task.created +task.completed +task.failed + +job.created +job.completed +job.failed +job.retry + +queue.depth +queue.wait_time + +worker.active +worker.capacity +worker.failure + +execution.duration +execution.failure +``` + +--- + +# 138. SLO + +未来可以设置: + +```text +Task queue latency +Task success rate +Job execution latency +Worker availability +``` + +例如: + +```text +95% Jobs +< 30s queue wait +``` + +--- + +# 139. Task Retention + +Task / Job / Execution 数量可能巨大。 + +需要: + +```text +retention policy +``` + +例如: + +```text +Execution logs: +30 days + +Task: +180 days + +Audit: +根据 Audit Policy +``` + +但: + +> 不允许未经策略自动删除 Audit。 + +--- + +# 140. Archive + +旧 Task: + +```text +active DB + ↓ +archive +``` + +大数据: + +```text +PostgreSQL + ↓ +Object Storage +``` + +UI 仍然可以查询 Archive。 + +第一版本可以只实现: + +```text +retention metadata +``` + +暂不实现复杂归档。 + +--- + +# 141. Task Search + +支持: + +```text +Task ID +Type +Status +Actor +Organization +Project +Action +Plugin +Date +``` + +例如: + +```text +plugin = github +status = failed +last 7 days +``` + +--- + +# 142. Admin Queue Dashboard + +建议: + +```text +/admin/tasks +/admin/jobs +/admin/workers +/admin/queues +``` + +显示: + +```text +Queue Depth +Running +Failed +Retrying +Workers +Throughput +Latency +``` + +--- + +# 143. Queue Dashboard + +```text +Queues + +default 120 +ai 32 +browser 8 +deployment 2 +``` + +点击: + +```text +Queue + ↓ +Jobs + ↓ +Workers +``` + +--- + +# 144. Worker Dashboard + +```text +worker-01 +──────────────── + +Status: +Busy + +Queues: +default, ai + +Concurrency: +5 / 5 + +Jobs: +job-123 +job-456 +... + +Heartbeat: +2 sec ago +``` + +--- + +# 145. Scheduler Dashboard + +```text +Schedules + +GitHub Sync +Every 10 min +Next: 10:40 +Healthy + +SEO Report +Every Monday +Next: Monday +Enabled +``` + +--- + +# 146. Scheduler Misfire + +如果 Scheduler 本身失败: + +```text +missed run +``` + +根据: + +```text +misfirePolicy +``` + +处理: + +```text +skip +run_once +run_all +``` + +--- + +# 147. Task Runtime 与 Notification + +Task Event: + +```text +task.completed +``` + +Notification Plugin 可以监听: + +```text +Task completed +``` + +发送: + +```text +Email +Slack +Telegram +Web notification +``` + +因此 Task Runtime 不需要知道: + +```text +Email +Slack +Telegram +``` + +--- + +# 148. Task Runtime 与 Plugin + +例如: + +```text +Cloudflare Plugin +``` + +提供: + +```text +cloudflare.dns.update +``` + +Task Runtime: + +```text +Task + ↓ +Job + ↓ +Action Runtime + ↓ +Cloudflare Action +``` + +--- + +# 149. Task Runtime 与 Resource + +Task 本身也可以是: + +```text +Resource +``` + +推荐: + +```text +core.task +core.job +core.execution +``` + +这样可以复用: + +```text +Resource Registry +Action Registry +Permission +UI +Audit +``` + +--- + +# 150. Task Actions + +至少: + +```text +core.task.create +core.task.pause +core.task.resume +core.task.cancel +core.task.retry +core.task.archive +``` + +Job: + +```text +core.job.retry +core.job.cancel +``` + +--- + +# 151. Task UI 自动生成 + +因为 Task 是 Resource: + +```text +Resource Metadata + ↓ +Generic List + ↓ +Generic Detail +``` + +可以自动生成基础 UI。 + +特殊任务: + +```text +Plugin +``` + +再提供: + +```text +Custom Task View +``` + +--- + +# 152. Task Event → Agent + +例如: + +```text +task.completed +``` + +Agent Subscription: + +```text +Agent Runtime +``` + +收到: + +```text +Observation +``` + +然后: + +```text +Evaluate + ↓ +Complete / Replan +``` + +--- + +# 153. Task Event → Workflow + +Workflow 可以: + +```text +On Task Completed +``` + +触发: + +```text +Next Task +``` + +形成: + +```text +Task A + ↓ +Event + ↓ +Workflow + ↓ +Task B +``` + +--- + +# 154. Task Event → Plugin + +Plugin 可以监听: + +```text +task.failed +``` + +例如: + +```text +Notification Plugin +``` + +发送告警。 + +--- + +# 155. 最终完整执行模型 + +```text + User + │ + Agent + │ + Goal + │ + Planner + │ + Task + │ + ┌─────┴─────┐ + │ │ + Job A Job B + │ │ + └─────┬─────┘ + │ + Queue + │ + ┌─────┴─────┐ + │ │ + Worker A Worker B + │ │ + └─────┬─────┘ + │ + Action Runtime + │ + ┌──────┴──────┐ + │ │ + Plugin Core + │ │ + └──────┬──────┘ + │ + Execution + │ + Event + │ + ┌────────────┼────────────┐ + │ │ │ + UI Agent Workflow +``` + +--- + +# 156. Zcode 实现要求 + +必须新增/完善: + +```text +packages/task/ +packages/job/ +packages/queue/ +packages/worker/ +packages/scheduler/ +packages/execution/ +``` + +如果当前项目已经存在类似模块: + +> 不要重复创建第二套 Runtime,应将现有实现迁移/合并到统一 Runtime。 + +--- + +# 157. Zcode 禁止事项 + +禁止: + +```text +Plugin 自建 Queue +Plugin 自建 Worker + +Agent 自建 Queue +Agent 自建 Worker + +Workflow 自己执行长任务 + +Controller 直接执行 Action + +MCP 直接执行外部业务 + +UI 直接调用 Plugin 内部函数 + +Scheduler 直接执行业务逻辑 +``` + +所有执行必须最终进入: + +```text +Action Runtime +``` + +--- + +# 158. 第一阶段必须完成 + +Zcode 第一阶段: + +```text +Task CRUD +Job CRUD +Execution +Redis Queue +Worker +Retry +Progress +Cancel +``` + +必须真正可运行。 + +--- + +# 159. 第二阶段 + +实现: + +```text +Scheduler +Cron +Event Trigger +Job Dependency +Parallel Jobs +Batch Task +Task Budget +Concurrency +Resource Group +``` + +--- + +# 160. 第三阶段 + +实现: + +```text +Outbox +Lease Recovery +Dead Letter Queue +Replay +Advanced Retry +Worker Tags +Worker Scaling Interface +Artifact +Retention +Advanced Observability +``` + +--- + +# 161. 最小可运行 Demo + +必须能够运行: + +```text +POST /api/tasks +``` + +创建: + +```text +Task: +Generate 10 test jobs +``` + +系统: + +```text +Task + ↓ +10 Jobs + ↓ +Redis Queue + ↓ +Worker + ↓ +Action + ↓ +10 Executions +``` + +最终: + +```text +Task: +completed + +Progress: +100% + +Jobs: +10 / 10 + +Executions: +10 +``` + +--- + +# 162. Batch Demo + +创建: + +```text +Task: +Generate 100 items +``` + +系统: + +```text +1 Task +100 Jobs +N Workers +``` + +例如: + +```text +Worker 1 → Job 1-5 +Worker 2 → Job 6-10 +Worker 3 → Job 11-15 +... +``` + +最终: + +```text +100 completed +``` + +Agent 不参与每个 Job 的循环。 + +--- + +# 163. Retry Demo + +Job: + +```text +test.retry +``` + +第一次: + +```text +fail retryable=true +``` + +自动: + +```text +retry +``` + +第二次: + +```text +success +``` + +结果: + +```text +Job: +completed + +Attempts: +2 + +Executions: +2 +``` + +--- + +# 164. Cancel Demo + +创建: + +```text +10 long-running Jobs +``` + +用户: + +```text +Cancel Task +``` + +系统: + +```text +queued Jobs → cancelled +running Jobs → abort +``` + +最终: + +```text +Task: +cancelled +``` + +--- + +# 165. Scheduler Demo + +创建: + +```text +Every minute +``` + +Scheduler: + +```text +Schedule + ↓ +Task + ↓ +Job + ↓ +Queue + ↓ +Worker +``` + +每分钟自动创建任务。 + +--- + +# 166. Worker Recovery Demo + +启动: + +```text +Worker A +``` + +执行 Job。 + +强制杀掉: + +```text +Worker A +``` + +等待 Lease: + +```text +expired +``` + +启动: + +```text +Worker B +``` + +Job: + +```text +requeued +``` + +Worker B: + +```text +execute +``` + +--- + +# 167. 最终验收标准 + +以下全部成立才算完成: + +```text +[ ] Task 是统一任务模型 +[ ] Job 是统一调度单位 +[ ] Execution 是统一执行记录 +[ ] Queue 不包含业务逻辑 +[ ] Worker 不包含业务逻辑 +[ ] Action Runtime 是唯一执行入口 +[ ] Redis Queue 可工作 +[ ] Worker Lease 可工作 +[ ] Worker Heartbeat 可工作 +[ ] Retry 可工作 +[ ] Idempotency 可工作 +[ ] Progress 可工作 +[ ] Cancellation 可工作 +[ ] Pause/Resume 可工作 +[ ] Batch Task 可工作 +[ ] Job Dependency 可工作 +[ ] Scheduler 可工作 +[ ] Cron 可工作 +[ ] Event Trigger 可工作 +[ ] Task Budget 可工作 +[ ] Concurrency 可工作 +[ ] Resource Group 可工作 +[ ] Task Event 可工作 +[ ] Audit 可工作 +[ ] Agent 可以创建 Task +[ ] Agent 不直接控制 Worker +[ ] Plugin 可以创建 Task +[ ] Plugin 不创建自己的 Queue +[ ] Workflow 可以创建 Task +[ ] MCP 创建的工作进入 Task/Action Runtime +[ ] UI 可以实时观察 Task +[ ] CLI 与 UI 使用同一 Task Runtime +``` + +--- + +# 168. DevOS 最终执行 Golden Rule + +以后 DevOS 中任何需要: + +```text +异步 +批量 +延迟 +重试 +定时 +长时间 +并发 +后台 +可恢复 +可观察 +可取消 +``` + +的工作: + +**全部进入 Task Runtime。** + +统一模型: + +```text +Task + ↓ +Job + ↓ +Queue + ↓ +Worker + ↓ +Action Runtime + ↓ +Execution + ↓ +Event +``` + +Agent: + +```text +决定做什么 +``` + +Task: + +```text +记录要做什么 +``` + +Job: + +```text +定义具体工作单元 +``` + +Queue: + +```text +决定什么时候做 +``` + +Worker: + +```text +负责执行 +``` + +Action Runtime: + +```text +负责如何安全地执行 +``` + +Execution: + +```text +记录实际发生了什么 +``` + +Event: + +```text +告诉系统发生了什么 +``` + +这套模型必须成为 DevOS 所有 App、Plugin、MCP、Skill、Agent、Workflow、Scheduler 的**唯一异步执行基础设施**。 diff --git a/Docs/DevOS-Platform-v2/10_EVENT_AUDIT_OBSERVABILITY_RUNTIME.md b/Docs/DevOS-Platform-v2/10_EVENT_AUDIT_OBSERVABILITY_RUNTIME.md new file mode 100644 index 0000000..95bb5a8 --- /dev/null +++ b/Docs/DevOS-Platform-v2/10_EVENT_AUDIT_OBSERVABILITY_RUNTIME.md @@ -0,0 +1,3498 @@ + +# DevOS Event / Audit / Observability Runtime + +> Version: 1.0 +> Status: Implementation Specification +> Target: Zcode +> Previous: 09_TASK_JOB_QUEUE_RUNTIME.md +> Next: 11_* + +--- + +# 1. 目标 + +DevOS 必须建立统一的: + +- Event Runtime +- Event Bus +- Audit Runtime +- Log Runtime +- Metric Runtime +- Trace Runtime +- Notification Runtime +- Observability Runtime + +所有 Core、Plugin、MCP、Skill、Agent、Task、Job、Action +都必须接入这一套基础设施。 + +禁止每个模块自己实现: + +- event emitter +- audit logger +- operation log +- notification +- task log +- agent log +- plugin log + +必须统一进入 DevOS Runtime。 + +--- + +# 2. 核心原则 + +DevOS 中所有重要行为都应该形成: + +```text +Action + ↓ +Execution + ↓ +Event + ├── Audit + ├── Log + ├── Metric + ├── Trace + ├── Notification + ├── Task Update + ├── Agent Observation + └── Webhook / Integration +```` + +最终形成: + +```text + ┌───────────────┐ + │ Action │ + └───────┬───────┘ + ↓ + ┌───────────────┐ + │ Execution │ + └───────┬───────┘ + ↓ + ┌───────────────┐ + │ Event │ + └───────┬───────┘ + ┌───────────┼───────────┐ + ↓ ↓ ↓ + Audit Log Metric + ↓ ↓ ↓ + Security Debugging Monitoring + │ + └──────────┬──────────┘ + ↓ + Observability + ↓ + Human / Agent / UI +``` + +--- + +# 3. Event 与 Audit 的区别 + +必须严格区分。 + +## Event + +Event 表示: + +> 系统中发生了一件事情。 + +例如: + +```text +user.created +website.scanned +task.created +task.completed +job.failed +server.deployed +agent.run.completed +plugin.installed +``` + +Event 是系统运行机制的一部分。 + +--- + +## Audit + +Audit 表示: + +> 谁,在什么上下文中,对什么对象,执行了什么行为,以及结果是什么。 + +例如: + +```text +User Alice + ↓ +Action: server.production.deploy + ↓ +Server: srv-001 + ↓ +Result: success +``` + +Audit 是安全、合规、追责记录。 + +--- + +# 4. Event 类型 + +Event 必须使用 namespace。 + +格式: + +```text +.. +``` + +例如: + +```text +core.user.created + +core.user.updated + +core.user.deleted + +core.task.created + +core.task.started + +core.task.completed + +core.task.failed + +core.job.queued + +core.job.started + +core.job.completed + +core.job.failed + +core.execution.started + +core.execution.completed + +core.execution.failed + +agent.run.started + +agent.run.completed + +agent.run.failed + +plugin.installed + +plugin.uninstalled + +plugin.enabled + +plugin.disabled + +mcp.connected + +mcp.disconnected + +seo.website.scanned + +seo.article.generated + +devops.server.deployed +``` + +禁止使用: + +```text +created +updated +failed +success +``` + +这种没有 namespace 的 Event。 + +--- + +# 5. Event Schema + +推荐: + +```ts +export interface DevEvent { + id: string + + type: string + + version: number + + timestamp: Date + + organizationId?: string + + projectId?: string + + actor?: EventActor + + resource?: EventResource + + payload: T + + metadata?: Record + + correlationId?: string + + causationId?: string + + requestId?: string + + executionId?: string + + taskId?: string + + jobId?: string +} +``` + +--- + +# 6. Event Actor + +```ts +export interface EventActor { + type: 'user' | 'agent' | 'service' | 'system' + + id?: string + + name?: string +} +``` + +例如: + +```json +{ + "type": "agent", + "id": "agent-seo" +} +``` + +--- + +# 7. Event Resource + +```ts +export interface EventResource { + type: string + + id: string + + name?: string +} +``` + +例如: + +```json +{ + "type": "seo.website", + "id": "website_123" +} +``` + +--- + +# 8. Correlation ID + +必须支持: + +```text +correlationId +``` + +用于把多个操作关联起来。 + +例如: + +```text +User Request + correlationId = abc + ↓ +Agent Run + ↓ +Task + ↓ +Job + ↓ +Action + ↓ +Execution + ↓ +External API +``` + +所有下游 Event 都应该携带: + +```text +correlationId = abc +``` + +这样 UI 可以展示完整执行链。 + +--- + +# 9. Causation ID + +必须支持: + +```text +causationId +``` + +表示: + +> 当前 Event 是由哪个 Event 导致的。 + +例如: + +```text +website.updated + ↓ +website.scan.requested + ↓ +task.created + ↓ +job.created + ↓ +execution.started +``` + +这样可以构建事件因果链。 + +--- + +# 10. Event Bus + +实现统一: + +```ts +interface EventBus { + publish(event: DevEvent): Promise + + publishMany(events: DevEvent[]): Promise + + subscribe( + pattern: string, + handler: EventHandler + ): Promise + + unsubscribe( + subscriptionId: string + ): Promise +} +``` + +--- + +# 11. Event Handler + +```ts +export interface EventHandler { + ( + event: DevEvent, + context: EventContext + ): Promise +} +``` + +Context: + +```ts +export interface EventContext { + correlationId: string + + signal: AbortSignal + + metadata: Record +} +``` + +--- + +# 12. Event 不应该直接调用业务逻辑 + +错误: + +```ts +eventBus.subscribe( + 'seo.website.updated', + async event => { + await db.website.update(...) + await crawler.scan(...) + await sendEmail(...) + } +) +``` + +Event Handler 应该创建正常的: + +```text +Task +Job +Action +``` + +而不是绕过 Runtime。 + +正确: + +```text +Event + ↓ +Event Handler + ↓ +Task + ↓ +Job + ↓ +Action Runtime +``` + +--- + +# 13. Event Delivery + +默认采用: + +```text +At Least Once +``` + +不假设: + +```text +Exactly Once +``` + +因此 Handler 必须支持: + +```text +idempotency +``` + +--- + +# 14. Event Inbox + +对于重要 Consumer,应实现 Inbox。 + +```ts +interface EventInbox { + eventId: string + + consumerId: string + + processedAt?: Date + + status: 'pending' | 'processed' | 'failed' + + error?: string +} +``` + +处理逻辑: + +```text +Receive Event + ↓ +Check Inbox + ↓ +Already processed? + ↓ Yes ↓ No + Ignore Execute + ↓ + Mark Done +``` + +防止重复消费。 + +--- + +# 15. Event Outbox + +必须实现: + +```text +Transactional Outbox +``` + +禁止: + +```ts +await db.task.create() + +await eventBus.publish(...) +``` + +因为可能出现: + +```text +DB 成功 +Event 失败 +``` + +导致系统状态不一致。 + +--- + +# 16. Outbox Schema + +```ts +interface OutboxEvent { + id: string + + type: string + + aggregateType?: string + + aggregateId?: string + + payload: unknown + + status: 'pending' | 'published' | 'failed' + + attempts: number + + nextAttemptAt?: Date + + createdAt: Date + + publishedAt?: Date + + error?: string +} +``` + +Transaction: + +```text +DB Transaction + ├── Business Data + └── Outbox Event + ↓ + Commit + ↓ + Outbox Worker + ↓ + Event Bus +``` + +--- + +# 17. Event Retention + +Event 必须区分: + +### Operational Event + +例如: + +```text +job.progress +worker.heartbeat +execution.log +``` + +可以短期保存。 + +### Domain Event + +例如: + +```text +website.created +server.deployed +user.created +``` + +应该长期保存。 + +### Audit Event + +根据安全/合规要求长期保存。 + +--- + +# 18. Audit Runtime + +实现: + +```ts +interface AuditService { + record(input: AuditInput): Promise +} +``` + +--- + +# 19. Audit Schema + +```ts +interface AuditRecord { + id: string + + timestamp: Date + + organizationId?: string + + projectId?: string + + actorType: 'user' | 'agent' | 'service' | 'system' + + actorId?: string + + actionId: string + + resourceType?: string + + resourceId?: string + + status: 'success' | 'failed' | 'denied' + + requestId?: string + + executionId?: string + + taskId?: string + + jobId?: string + + correlationId?: string + + inputSummary?: unknown + + outputSummary?: unknown + + error?: { + code?: string + message: string + } + + ip?: string + + userAgent?: string + + metadata?: Record +} +``` + +--- + +# 20. Audit 必须在 Action Runtime 中自动生成 + +不能依赖开发者手动调用。 + +错误: + +```ts +await action() + +await audit.record(...) +``` + +正确: + +```text +ActionRuntime + ↓ +Authorization + ↓ +Audit Start + ↓ +Execute + ↓ +Audit Result +``` + +--- + +# 21. Audit 权限 + +Audit 本身也是敏感 Resource: + +```text +core.audit +``` + +Actions: + +```text +core.audit.list +core.audit.get +core.audit.export +``` + +普通用户不能查看所有 Audit。 + +必须支持: + +```text +organization scope +project scope +resource scope +actor scope +``` + +--- + +# 22. Audit 不保存敏感原文 + +禁止直接保存: + +```text +password +access_token +refresh_token +api_key +private_key +cookie +secret +``` + +必须经过: + +```text +Sensitive Data Redaction +``` + +例如: + +```json +{ + "apiKey": "[REDACTED]", + "password": "[REDACTED]" +} +``` + +--- + +# 23. Log Runtime + +实现统一: + +```ts +interface Logger { + debug(message: string, meta?: object): void + + info(message: string, meta?: object): void + + warn(message: string, meta?: object): void + + error(message: string, meta?: object): void +} +``` + +--- + +# 24. Structured Logging + +禁止: + +```ts +console.log( + `Deploy server ${serverId} failed` +) +``` + +应该: + +```ts +logger.error( + 'Server deployment failed', + { + serverId, + executionId, + taskId, + correlationId, + errorCode + } +) +``` + +--- + +# 25. Log Schema + +```ts +interface LogEntry { + timestamp: Date + + level: + | 'debug' + | 'info' + | 'warn' + | 'error' + + message: string + + service?: string + + module?: string + + organizationId?: string + + actorId?: string + + correlationId?: string + + requestId?: string + + executionId?: string + + taskId?: string + + jobId?: string + + metadata?: Record +} +``` + +--- + +# 26. Log 与 Event 不混合 + +Event: + +```text +website.scan.completed +``` + +Log: + +```text +crawler request took 1.2s +``` + +Event 是系统事实。 + +Log 是运行过程信息。 + +--- + +# 27. Task Log + +Task 必须能够关联 Log。 + +例如: + +```text +Task + ├── Event timeline + ├── Jobs + ├── Executions + ├── Logs + ├── Artifacts + └── Audit +``` + +UI 可以: + +```text +Task #123 +────────────────────── +Timeline +Logs +Jobs +Executions +Artifacts +Audit +``` + +--- + +# 28. Metric Runtime + +必须提供: + +```ts +interface Metrics { + counter( + name: string, + value?: number, + labels?: Record + ): void + + gauge( + name: string, + value: number, + labels?: Record + ): void + + histogram( + name: string, + value: number, + labels?: Record + ): void +} +``` + +--- + +# 29. 标准 Metric + +至少实现: + +```text +devos_action_total + +devos_action_success_total + +devos_action_failed_total + +devos_action_duration_ms + +devos_task_total + +devos_task_completed_total + +devos_task_failed_total + +devos_job_total + +devos_job_retry_total + +devos_job_duration_ms + +devos_queue_depth + +devos_worker_active + +devos_worker_unhealthy + +devos_agent_run_total + +devos_agent_tokens_total + +devos_agent_cost_total + +devos_mcp_request_total + +devos_mcp_error_total +``` + +--- + +# 30. Metric Label + +推荐: + +```text +action_id +namespace +status +queue +worker +plugin +``` + +禁止把: + +```text +user_id +request_id +execution_id +``` + +这种高基数字段作为 Metric Label。 + +这些应该进入 Log/Trace。 + +--- + +# 31. Trace Runtime + +DevOS 应支持分布式 Trace。 + +核心: + +```text +traceId +spanId +parentSpanId +``` + +例如: + +```text +HTTP Request + trace + ↓ +Agent Run + ↓ +Task + ↓ +Job + ↓ +Action + ↓ +MCP + ↓ +External API +``` + +--- + +# 32. Trace Schema + +```ts +interface TraceContext { + traceId: string + + spanId: string + + parentSpanId?: string +} +``` + +所有 Runtime Context 应该能够携带 Trace。 + +--- + +# 33. Action Trace + +Action Runtime 自动创建: + +```text +action.execute +``` + +Span: + +```text +action.execute +├── authorization +├── validation +├── transaction +├── handler +├── external-call +└── event-publish +``` + +--- + +# 34. Agent Trace + +Agent Run: + +```text +agent.run + ├── goal.parse + ├── capability.search + ├── planning + ├── task.create + ├── action.execute + ├── observation + ├── evaluation + └── completion +``` + +注意: + +**不要记录隐藏 Chain of Thought。** + +只记录: + +```text +decision summary +selected capability +action +result +reason summary +``` + +--- + +# 35. Agent Observation Event + +Agent 可以订阅: + +```text +task.completed +task.failed +job.completed +job.failed +execution.completed +execution.failed +``` + +然后: + +```text +Observation + ↓ +Agent Evaluation + ↓ +Continue +Replan +Retry +Ask Human +Finish +``` + +--- + +# 36. Notification Runtime + +实现: + +```ts +interface NotificationService { + notify(input: NotificationInput): Promise +} +``` + +支持: + +```text +in-app +email +webhook +Slack +Discord +Telegram +``` + +具体 Provider 应该 Plugin 化。 + +--- + +# 37. Notification Resource + +定义: + +```text +core.notification +core.notification.channel +core.notification.preference +``` + +Actions: + +```text +core.notification.send +core.notification.channel.create +core.notification.channel.update +core.notification.channel.delete +``` + +--- + +# 38. Notification Event + +例如: + +```text +task.failed +agent.approval.required +server.deployment.failed +budget.exceeded +worker.unhealthy +``` + +通过 Notification Policy: + +```text +Event + ↓ +Notification Rule + ↓ +Channel + ↓ +Notification +``` + +--- + +# 39. Notification Rule + +```ts +interface NotificationRule { + id: string + + name: string + + eventPattern: string + + enabled: boolean + + conditions?: Record + + channels: string[] + + template?: string + + cooldownSeconds?: number +} +``` + +例如: + +```json +{ + "eventPattern": "core.task.failed", + "channels": ["email-admin"], + "cooldownSeconds": 300 +} +``` + +--- + +# 40. Notification 防爆 + +不能: + +```text +1000 jobs failed +↓ +1000 emails +``` + +必须支持: + +```text +deduplication +aggregation +cooldown +rate limit +batch notification +``` + +例如: + +```text +100 jobs failed + ↓ +5 minutes aggregation + ↓ +1 notification +``` + +--- + +# 41. Webhook Event Sink + +DevOS 可以把 Event 发送到外部 Webhook: + +```text +core.webhook +``` + +配置: + +```ts +interface WebhookEndpoint { + id: string + + url: string + + events: string[] + + enabled: boolean + + secret?: string + + headers?: Record +} +``` + +必须支持: + +```text +signature +retry +timeout +backoff +dead letter +``` + +--- + +# 42. Webhook Security + +请求应该包含: + +```text +X-DevOS-Event +X-DevOS-Event-Id +X-DevOS-Timestamp +X-DevOS-Signature +``` + +Signature: + +```text +HMAC-SHA256 +``` + +防止伪造。 + +--- + +# 43. Observability Resource + +统一: + +```text +core.event +core.audit +core.log +core.metric +core.trace +core.notification +``` + +但: + +**不是所有 Resource 都需要完整 CRUD UI。** + +例如: + +```text +Metric +Trace +Log +``` + +主要提供: + +```text +search +filter +view +aggregation +``` + +--- + +# 44. Event Resource Actions + +```text +core.event.list +core.event.get +core.event.search +core.event.replay +``` + +Replay 必须经过权限检查。 + +禁止普通用户随意 Replay: + +```text +payment.completed +server.deployed +``` + +这种高风险 Event。 + +--- + +# 45. Event Replay + +Event Replay 不应该直接重新执行原始 Handler。 + +应该: + +```text +Event + ↓ +Replay Request + ↓ +Authorization + ↓ +New Task / Job + ↓ +Action Runtime +``` + +并产生新的: + +```text +correlationId +``` + +以及: + +```text +causationId = originalEventId +``` + +--- + +# 46. Observability API + +提供: + +```http +GET /api/events +GET /api/events/:id + +GET /api/audits +GET /api/audits/:id + +GET /api/logs + +GET /api/metrics + +GET /api/traces/:traceId + +GET /api/tasks/:id/timeline + +GET /api/executions/:id/logs +``` + +--- + +# 47. Task Timeline API + +这是 DevOS UI 最重要的接口之一: + +```http +GET /api/tasks/:taskId/timeline +``` + +返回: + +```json +[ + { + "timestamp": "...", + "type": "task.created" + }, + { + "timestamp": "...", + "type": "job.queued" + }, + { + "timestamp": "...", + "type": "job.started" + }, + { + "timestamp": "...", + "type": "execution.started" + }, + { + "timestamp": "...", + "type": "execution.completed" + }, + { + "timestamp": "...", + "type": "job.completed" + }, + { + "timestamp": "...", + "type": "task.completed" + } +] +``` + +--- + +# 48. UI:Task Timeline + +必须提供: + +```text +Task #123 +──────────────────────────────── + +● Task created +│ +● Job #1 queued +│ +● Job #1 started +│ +● Website scan started +│ +● MCP request +│ +● Action completed +│ +● Job #1 completed +│ +● Task completed +``` + +点击任意节点: + +```text +Event +Execution +Logs +Audit +Trace +Input +Output +``` + +--- + +# 49. UI:Global Event Explorer + +提供: + +```text +Events +────────────────────────────── + +Search events... + +Type +Actor +Resource +Status +Organization +Project +Time Range + +────────────────────────────── + +event +timestamp +actor +resource +correlation +``` + +--- + +# 50. UI:Audit Explorer + +提供: + +```text +Audit +────────────────────────────── + +Actor +Action +Resource +Status +Time +Organization +Project + +────────────────────────────── + +Alice +server.deploy +server-001 +SUCCESS +``` + +支持: + +```text +Search +Filter +Export +Detail +``` + +--- + +# 51. UI:Execution Detail + +Execution 页面: + +```text +Execution #123 + +Status +Duration +Action +Actor +Task +Job + +────────────────── + +Input +Output +Logs +Trace +Events +Audit +Error +``` + +--- + +# 52. UI:Agent Run + +Agent Run: + +```text +Agent Run #123 +──────────────────────────── + +Goal + +Status + +Budget +Tokens +Cost +Iterations + +──────────────────────────── + +Plan + +1. Search capabilities +2. Create task +3. Execute scan +4. Analyze result +5. Generate report + +──────────────────────────── + +Observations + +Actions + +Tasks + +Events + +Result +``` + +不要显示隐藏思维链。 + +--- + +# 53. Error Model + +统一 Error: + +```ts +interface DevOSError { + code: string + + message: string + + category: + | 'validation' + | 'authorization' + | 'not_found' + | 'conflict' + | 'rate_limit' + | 'timeout' + | 'external' + | 'internal' + + retryable: boolean + + details?: unknown + + cause?: string +} +``` + +--- + +# 54. Error Event + +统一: + +```text +core.execution.failed +core.job.failed +core.task.failed +``` + +Payload: + +```json +{ + "error": { + "code": "EXTERNAL_TIMEOUT", + "category": "timeout", + "retryable": true + } +} +``` + +--- + +# 55. Observability Correlation + +所有日志/Event/Audit/Trace 至少应该尽可能携带: + +```text +organizationId +projectId +actor +requestId +correlationId +taskId +jobId +executionId +traceId +``` + +形成: + +```text +Organization + ↓ +Project + ↓ +Actor + ↓ +Request + ↓ +Correlation + ↓ +Task + ↓ +Job + ↓ +Execution + ↓ +Trace + ↓ +Event + ↓ +Log + ↓ +Audit +``` + +--- + +# 56. Storage + +推荐: + +## PostgreSQL + +保存: + +```text +Event +Audit +Outbox +Inbox +Notification +NotificationRule +Webhook +``` + +## Redis + +保存: + +```text +Event Queue +Pub/Sub +Rate Limit +Notification Dedup +Short-lived Trace State +``` + +## Log Storage + +第一阶段可以: + +```text +PostgreSQL +``` + +但必须抽象: + +```ts +interface LogStore +``` + +未来可以接: + +```text +Loki +Elasticsearch +OpenSearch +ClickHouse +``` + +--- + +# 57. Metric Storage + +不要把高频 Metric 永久写 PostgreSQL。 + +设计: + +```ts +interface MetricProvider { + counter(...) + + gauge(...) + + histogram(...) +} +``` + +默认可以接: + +```text +Prometheus / OpenTelemetry +``` + +--- + +# 58. Trace Provider + +设计: + +```ts +interface TraceProvider { + startSpan(...) + + endSpan(...) + + addEvent(...) + + setAttribute(...) +} +``` + +推荐: + +```text +OpenTelemetry +``` + +不要自行实现完整分布式 Trace 协议。 + +--- + +# 59. OpenTelemetry Integration + +DevOS 应尽量兼容: + +```text +OpenTelemetry +``` + +统一生成: + +```text +Trace +Span +Metric +Log correlation +``` + +这样以后可以接: + +```text +Grafana +Prometheus +Tempo +Loki +Jaeger +``` + +而无需修改业务代码。 + +--- + +# 60. Event-driven Architecture + +DevOS 不应该成为纯 CRUD Backend。 + +应该逐渐形成: + +```text +Command + ↓ +Action + ↓ +State Change + ↓ +Event + ↓ +Reaction +``` + +例如: + +```text +server.deploy + ↓ +server.updated + ↓ +server.deployment.completed + ↓ +notification + ↓ +audit + ↓ +agent observation +``` + +--- + +# 61. Event 与 Agent + +Agent 不应该轮询数据库: + +错误: + +```text +while true: + SELECT task WHERE status = completed +``` + +应该: + +```text +Event Bus + ↓ +Agent Observation +``` + +Agent 可以订阅: + +```text +task.completed +task.failed +job.failed +approval.completed +``` + +--- + +# 62. Event 与 Plugin + +Plugin 安装后可以声明: + +```ts +interface PluginEventSubscription { + pattern: string + + handler: string +} +``` + +例如 SEO Plugin: + +```text +core.task.completed +seo.website.updated +``` + +但 Handler 最终必须通过: + +```text +Action Runtime +Task Runtime +``` + +执行业务操作。 + +--- + +# 63. Event 与 MCP + +MCP 不应该拥有自己的 Event System。 + +MCP: + +```text +MCP request + ↓ +Action Runtime + ↓ +Execution + ↓ +Event +``` + +如果外部 MCP 触发 DevOS: + +```text +MCP + ↓ +Action + ↓ +Task + ↓ +Event +``` + +--- + +# 64. Event 与 Scheduler + +Scheduler 产生: + +```text +schedule.triggered +``` + +然后: + +```text +Schedule + ↓ +Event + ↓ +Task / Agent Goal +``` + +例如: + +```text +Every day 09:00 + ↓ +schedule.triggered + ↓ +Agent Goal + ↓ +Task +``` + +--- + +# 65. Event 与 Webhook + +外部: + +```text +GitHub +Stripe +Cloudflare +CI/CD +``` + +发送: + +```text +Webhook + ↓ +Verify + ↓ +Normalize + ↓ +Event + ↓ +Event Bus +``` + +Webhook Handler 不应该直接修改业务数据。 + +--- + +# 66. Event Schema Versioning + +Event 必须有: + +```text +version +``` + +例如: + +```text +seo.website.scanned v1 +seo.website.scanned v2 +``` + +Consumer 必须明确支持版本。 + +禁止无版本 Event Schema。 + +--- + +# 67. Backward Compatibility + +推荐: + +```text +v1 +v2 +``` + +同时支持一段时间。 + +禁止直接修改: + +```text +v1 payload +``` + +导致旧 Plugin 崩溃。 + +--- + +# 68. Event Naming Rules + +统一: + +```text +.. +``` + +推荐: + +```text +website.created +website.updated +website.deleted +website.scanned +website.published +``` + +不要: + +```text +createWebsite +websiteCreate +scanWebsiteNow +``` + +--- + +# 69. Security Event + +必须支持安全事件: + +```text +security.login.success +security.login.failed +security.permission.denied +security.api_key.created +security.api_key.revoked +security.session.created +security.session.revoked +security.suspicious_activity +``` + +这些 Event 可以进入: + +```text +Audit +Notification +Security Dashboard +``` + +--- + +# 70. Approval Event + +与前面的危险 Action 集成: + +```text +approval.requested +approval.approved +approval.rejected +approval.expired +``` + +流程: + +```text +Agent + ↓ +Dangerous Action + ↓ +Approval Required + ↓ +approval.requested + ↓ +Human + ↓ +approval.approved + ↓ +Action Runtime + ↓ +Execution +``` + +--- + +# 71. Budget Event + +Agent / Task / Organization Budget: + +```text +budget.warning +budget.exceeded +budget.blocked +``` + +例如: + +```text +Agent token budget > 80% + ↓ +budget.warning +``` + +超过: + +```text +budget.exceeded + ↓ +Agent stopped +``` + +--- + +# 72. Health Event + +Worker: + +```text +worker.started +worker.healthy +worker.unhealthy +worker.stopped +``` + +Queue: + +```text +queue.backpressure +queue.stalled +``` + +Plugin: + +```text +plugin.health.failed +``` + +MCP: + +```text +mcp.health.failed +``` + +--- + +# 73. Observability Dashboard + +DevOS 首页应该提供基础: + +```text +System Health + +Tasks +Jobs +Workers +Queues +Actions +Agents +MCP +Plugins +Errors +Costs +``` + +例如: + +```text +Tasks + Running 12 + Failed 2 + Completed 1234 + +Jobs + Queued 31 + Running 12 + Retry 4 + +Workers + Healthy 8 + Unhealthy 1 + +Agents + Running 4 + Token usage 72% + +Errors + Last hour 17 +``` + +--- + +# 74. Health Check + +所有 Runtime 必须提供: + +```text +health() +``` + +例如: + +```ts +interface HealthCheck { + name: string + + status: 'healthy' | 'degraded' | 'unhealthy' + + latencyMs?: number + + details?: Record +} +``` + +系统: + +```text +GET /health +GET /health/ready +GET /health/live +``` + +--- + +# 75. Readiness + +Readiness 应检查: + +```text +PostgreSQL +Redis +Queue +Worker +Event Bus +``` + +如果数据库不可用: + +```text +ready = false +``` + +--- + +# 76. Plugin Health + +Plugin Runtime 必须支持: + +```text +Plugin + ├── enabled + ├── installed + ├── configured + └── healthy +``` + +Plugin Health 可以产生: + +```text +plugin.health.failed +``` + +--- + +# 77. MCP Health + +MCP Server: + +```text +connected +degraded +disconnected +``` + +产生: + +```text +mcp.connected +mcp.disconnected +mcp.health.failed +``` + +--- + +# 78. Cost Observability + +Agent / Action / MCP 都应该可以记录成本: + +```ts +interface UsageRecord { + provider?: string + + model?: string + + tokensInput?: number + + tokensOutput?: number + + requests?: number + + estimatedCost?: number + + currency?: string +} +``` + +最终形成: + +```text +Organization + ↓ +Project + ↓ +Agent + ↓ +Task + ↓ +Job + ↓ +Execution + ↓ +Provider + ↓ +Cost +``` + +--- + +# 79. Cost Event + +例如: + +```text +ai.usage.recorded +ai.budget.warning +ai.budget.exceeded +``` + +--- + +# 80. 数据脱敏 + +所有: + +```text +Log +Event +Audit +Trace +Notification +``` + +进入 Storage 前都可以经过: + +```ts +RedactionService +``` + +接口: + +```ts +interface RedactionService { + redact(input: unknown): unknown +} +``` + +默认敏感字段: + +```text +password +token +accessToken +refreshToken +apiKey +secret +privateKey +authorization +cookie +``` + +--- + +# 81. Observability Middleware + +Action Runtime: + +```text +Request + ↓ +Trace Middleware + ↓ +Auth Middleware + ↓ +Audit Middleware + ↓ +Metrics Middleware + ↓ +Logger Context + ↓ +Action + ↓ +Event +``` + +--- + +# 82. Runtime Context + +统一 Context: + +```ts +interface RuntimeContext { + requestId: string + + correlationId: string + + traceId?: string + + actor: Actor + + organizationId?: string + + projectId?: string + + taskId?: string + + jobId?: string + + executionId?: string + + metadata: Record + + signal: AbortSignal +} +``` + +Action / Task / Agent / MCP 都应该尽量复用。 + +--- + +# 83. Package Architecture + +Zcode 必须实现: + +```text +packages/ +├── event/ +│ ├── types/ +│ ├── registry/ +│ ├── bus/ +│ ├── publisher/ +│ ├── subscriber/ +│ ├── outbox/ +│ └── inbox/ +│ +├── audit/ +│ ├── runtime/ +│ ├── redaction/ +│ └── policy/ +│ +├── logging/ +│ ├── logger/ +│ ├── context/ +│ └── transport/ +│ +├── metrics/ +│ ├── registry/ +│ └── provider/ +│ +├── tracing/ +│ ├── runtime/ +│ └── provider/ +│ +├── notification/ +│ ├── runtime/ +│ ├── channels/ +│ ├── templates/ +│ └── rules/ +│ +└── observability/ + ├── timeline/ + ├── health/ + ├── search/ + └── dashboard/ +``` + +--- + +# 84. Database Models + +至少: + +```text +events +event_outbox +event_inbox + +audit_records + +notification_rules +notification_channels +notifications + +webhook_endpoints +webhook_deliveries +``` + +Log/Metric/Trace Storage 应通过 Provider 抽象。 + +--- + +# 85. Event Registry + +实现: + +```ts +interface EventDefinition { + type: string + + version: number + + description: string + + payloadSchema: ZodSchema + + sensitiveFields?: string[] +} +``` + +Plugin 可以注册: + +```ts +eventRegistry.register(...) +``` + +例如: + +```text +seo.website.scanned +``` + +--- + +# 86. Schema Validation + +Event Publish 时: + +```text +publish() + ↓ +Event Registry + ↓ +Find Definition + ↓ +Validate Payload + ↓ +Redact + ↓ +Persist Outbox + ↓ +Publish +``` + +未知 Event: + +```text +development: error +production: configurable +``` + +推荐生产环境也拒绝没有 Schema 的 Domain Event。 + +--- + +# 87. Event Permission + +Event 本身可以定义 visibility: + +```ts +visibility: + | 'public' + | 'organization' + | 'project' + | 'private' + | 'system' +``` + +例如: + +```text +core.user.created +``` + +不能让任意 Agent 读取完整 User Event。 + +必须经过: + +```text +Capability Discovery ++ +Permission ++ +Scope +``` + +--- + +# 88. Agent Event Access + +Agent 不能: + +```text +读取所有 Event +``` + +必须: + +```text +Agent Policy + ↓ +Allowed Event Types + ↓ +Organization Scope + ↓ +Resource Scope +``` + +--- + +# 89. Event Search + +支持: + +```text +type +actor +resource +organization +project +task +job +execution +correlationId +time range +status +``` + +例如: + +```http +GET /api/events? +type=core.execution.failed& +taskId=task_123 +``` + +--- + +# 90. Audit Search + +支持: + +```text +actor +action +resource +status +organization +project +time +ip +``` + +--- + +# 91. Timeline Aggregation + +Task Timeline 不应该查询十几个表后由前端拼接。 + +后端提供: + +```text +TimelineService +``` + +统一聚合: + +```text +Events +Audit +Executions +Jobs +Logs +Approvals +Notifications +``` + +然后输出: + +```ts +interface TimelineItem { + id: string + + timestamp: Date + + type: string + + title: string + + status?: string + + resource?: EventResource + + actor?: EventActor + + metadata?: unknown +} +``` + +--- + +# 92. Streaming + +Task/Agent/Execution 页面支持实时更新: + +推荐: + +```text +SSE +``` + +例如: + +```http +GET /api/tasks/:id/stream +``` + +事件: + +```text +task.progress +job.started +execution.log +execution.completed +task.completed +``` + +WebSocket 可以作为未来扩展。 + +第一阶段优先 SSE。 + +--- + +# 93. Streaming Architecture + +```text +Action + ↓ +Event Bus + ↓ +Event Stream + ↓ +SSE Gateway + ↓ +Browser +``` + +禁止 UI 直接连接 Worker。 + +--- + +# 94. Real-time Agent UI + +Agent Chat 可以实时显示: + +```text +Agent: +我正在分析目标... + +Capability: +seo.website.scan + +Task: +Task #123 created + +Execution: +Scanning website... + +Result: +Found 37 issues + +Agent: +正在生成修复计划... +``` + +所有这些都应该来自: + +```text +Event +``` + +而不是 Agent Runtime 直接操作 UI。 + +--- + +# 95. Audit 与 Agent + +Agent 执行: + +```text +Agent + ↓ +Action +``` + +Audit 必须记录: + +```text +actorType = agent +actorId = agent_x +``` + +同时应该保留: + +```text +initiatedByUser +``` + +如果数据模型需要: + +```ts +initiator?: { + type: 'user' | 'agent' | 'system' + id?: string +} +``` + +最终可以追溯: + +```text +User Alice + ↓ +Agent SEO + ↓ +Task + ↓ +Action + ↓ +Execution +``` + +--- + +# 96. Golden Rule + +整个 DevOS 的可观察性必须遵循: + +```text +ONE EVENT SYSTEM +ONE AUDIT SYSTEM +ONE LOGGING SYSTEM +ONE METRIC SYSTEM +ONE TRACE SYSTEM +ONE NOTIFICATION SYSTEM +``` + +禁止: + +```text +Plugin EventBus +Agent EventBus +Task EventBus +MCP EventBus +SEO EventBus +``` + +这些都必须接入: + +```text +DevOS Event Runtime +``` + +--- + +# 97. 与前面 Runtime 的完整关系 + +现在 DevOS Runtime 形成: + +```text + User + │ + Agent + │ + Goal + │ + Task + │ + Job + │ + Queue + │ + Worker + │ + Action + │ + Action Runtime + │ + Execution + │ + ┌────────┴────────┐ + ↓ ↓ + Event Result + │ + ┌───────┼────────┐ + ↓ ↓ ↓ + Audit Log Metric + │ │ │ + └───────┼────────┘ + ↓ + Trace + ↓ + Observability + │ + ┌──────┼──────┐ + ↓ ↓ ↓ + UI Agent Notification +``` + +--- + +# 98. Zcode 禁止事项 + +以下全部禁止: + +```text +❌ console.log 代替 Logger +❌ Plugin 自己实现 EventBus +❌ Agent 自己实现 EventBus +❌ MCP 自己保存业务 Event +❌ Action Handler 自己写 Audit +❌ Controller 自己写 Audit +❌ UI 自己轮询数据库 +❌ Agent 轮询数据库等待 Task +❌ Event Handler 直接修改业务数据库 +❌ Event Handler 绕过 Action Runtime +❌ 保存密码/token/private key +❌ 使用高基数字段作为 Metric Label +❌ 修改已发布 Event Schema +❌ 把 Chain of Thought 写入数据库 +``` + +--- + +# 99. Acceptance Criteria + +Zcode 完成后必须满足: + +## Event + +* [ ] Event Registry +* [ ] Event Schema +* [ ] Event Bus +* [ ] Publish +* [ ] Subscribe +* [ ] Event Version +* [ ] Correlation ID +* [ ] Causation ID +* [ ] Event Permission +* [ ] Event Search +* [ ] Event Replay +* [ ] Event Outbox +* [ ] Event Inbox +* [ ] Retry +* [ ] Dead Letter + +## Audit + +* [ ] Action 自动 Audit +* [ ] Success Audit +* [ ] Failed Audit +* [ ] Denied Audit +* [ ] Actor +* [ ] Resource +* [ ] Organization Scope +* [ ] Project Scope +* [ ] Redaction +* [ ] Audit Search +* [ ] Audit Export + +## Logging + +* [ ] Structured Logger +* [ ] Context +* [ ] Request ID +* [ ] Correlation ID +* [ ] Task ID +* [ ] Job ID +* [ ] Execution ID +* [ ] Redaction + +## Metrics + +* [ ] Counter +* [ ] Gauge +* [ ] Histogram +* [ ] Action Metrics +* [ ] Task Metrics +* [ ] Job Metrics +* [ ] Queue Metrics +* [ ] Worker Metrics +* [ ] Agent Metrics +* [ ] Cost Metrics + +## Trace + +* [ ] Trace ID +* [ ] Span +* [ ] Parent Span +* [ ] Action Trace +* [ ] Agent Trace +* [ ] MCP Trace +* [ ] External Call Trace +* [ ] OpenTelemetry Provider + +## Notification + +* [ ] Notification Runtime +* [ ] Channel +* [ ] Rule +* [ ] Template +* [ ] Email +* [ ] Webhook +* [ ] Deduplication +* [ ] Cooldown +* [ ] Aggregation +* [ ] Retry + +## UI + +* [ ] Event Explorer +* [ ] Audit Explorer +* [ ] Task Timeline +* [ ] Job Timeline +* [ ] Execution Detail +* [ ] Agent Run Detail +* [ ] Logs +* [ ] Trace +* [ ] Real-time SSE +* [ ] System Health Dashboard + +--- + +# 100. Integration Tests + +必须至少实现以下测试: + +### Test 1 + +```text +Action + ↓ +Execution + ↓ +Event + ↓ +Audit +``` + +验证整个链条存在。 + +### Test 2 + +```text +DB Transaction + ↓ +Outbox + ↓ +Event Bus +``` + +验证事务一致性。 + +### Test 3 + +重复 Event: + +```text +same eventId + ↓ +Inbox + ↓ +only once handler effect +``` + +### Test 4 + +Agent: + +```text +Goal + ↓ +Task + ↓ +Job + ↓ +Action + ↓ +Execution + ↓ +Event + ↓ +Agent Observation +``` + +### Test 5 + +Plugin: + +```text +Plugin + ↓ +Action + ↓ +Event + ↓ +Audit +``` + +### Test 6 + +MCP: + +```text +MCP + ↓ +Action Runtime + ↓ +Execution + ↓ +Event + ↓ +Audit +``` + +### Test 7 + +权限: + +```text +Unauthorized Event + ↓ +Access Denied +``` + +### Test 8 + +敏感数据: + +```text +password/token/apiKey + ↓ +Log/Audit/Event + ↓ +REDACTED +``` + +### Test 9 + +Task Timeline: + +```text +Task +Job +Execution +Event +Audit +Log +``` + +能够被统一聚合。 + +### Test 10 + +SSE: + +```text +Task running + ↓ +Event + ↓ +SSE + ↓ +Browser +``` + +验证实时 UI。 + +--- + +# 101. 最终架构 + +完成 10 之后,DevOS 的基础 Runtime 应该已经形成: + +```text +┌────────────────────────────────────────────┐ +│ DevOS │ +│ │ +│ Identity / RBAC / Organization │ +│ │ +│ Resource Registry │ +│ Action Registry │ +│ Capability Registry │ +│ │ +│ Agent Runtime │ +│ Skill Runtime │ +│ MCP Runtime │ +│ │ +│ Task Runtime │ +│ Job Runtime │ +│ Queue Runtime │ +│ Worker Runtime │ +│ Scheduler │ +│ │ +│ Action Runtime │ +│ Execution Runtime │ +│ │ +│ Event Runtime │ +│ Audit Runtime │ +│ Logging Runtime │ +│ Metrics Runtime │ +│ Trace Runtime │ +│ Notification Runtime │ +│ │ +│ Plugin Runtime │ +│ │ +│ UI Shell │ +└────────────────────────────────────────────┘ + │ + ↓ + ┌─────────────────┐ + │ App Extensions │ + ├─────────────────┤ + │ SEO │ + │ DevOps │ + │ CRM │ + │ Content │ + │ Marketing │ + │ Other Domains │ + └─────────────────┘ +``` + +--- + +# 102. 最重要的最终原则 + +DevOS 到目前为止必须严格遵守: + +```text +Resource + ↓ +Action + ↓ +Action Runtime + ↓ +Execution + ↓ +Event + ↓ +Observability +``` + +异步: + +```text +Task + ↓ +Job + ↓ +Queue + ↓ +Worker + ↓ +Action Runtime + ↓ +Execution + ↓ +Event +``` + +Agent: + +```text +Goal + ↓ +Agent + ↓ +Skill + ↓ +Capability + ↓ +Task + ↓ +Action + ↓ +Execution + ↓ +Event + ↓ +Observation + ↓ +Agent +``` + +Plugin: + +```text +Plugin + ├── Resource + ├── Action + ├── Skill + ├── MCP + ├── Workflow + ├── Event + └── UI + ↓ + DevOS Registry + ↓ + DevOS Runtime +``` + +**最终禁止任何模块建立第二套 Runtime。** + +DevOS 的核心不是: + +```text +一堆 CRUD +``` + +而是: + +```text +Resource ++ +Action ++ +Task ++ +Execution ++ +Event ++ +Agent ++ +Capability ++ +Observability +``` + +这才是整个 DevOS 能够持续扩展、让 SEO / DevOps / CRM / Content 等应用共享同一套底座的核心。 diff --git a/Docs/DevOS-Platform-v2/11_PLUGIN_RUNTIME.md b/Docs/DevOS-Platform-v2/11_PLUGIN_RUNTIME.md new file mode 100644 index 0000000..b8c7b5c --- /dev/null +++ b/Docs/DevOS-Platform-v2/11_PLUGIN_RUNTIME.md @@ -0,0 +1,3499 @@ + +# DevOS Plugin Runtime + +> Version: 1.0 +> Status: Implementation Specification +> Target: Zcode +> Previous: 10_EVENT_AUDIT_OBSERVABILITY_RUNTIME.md +> Next: 12_* + +--- + +# 1. 目标 + +DevOS Plugin Runtime 是整个 DevOS 的扩展系统。 + +Plugin 必须能够扩展: + +- Resource +- Action +- Capability +- Skill +- MCP +- Workflow +- Event +- UI +- Navigation +- Settings +- Dashboard +- Widget +- Notification +- Scheduler +- Worker Capability + +Plugin 不是简单的 npm package。 + +Plugin 是: + +> 可以被 DevOS 安装、配置、启停、升级、卸载,并向 DevOS Runtime 注册能力和 UI 的扩展单元。 + +--- + +# 2. 核心原则 + +Plugin 必须运行在 DevOS Runtime 之上。 + +正确: + +Plugin + ↓ +Plugin Runtime + ↓ +DevOS Registry + ↓ +DevOS Runtime + +禁止: + +Plugin + ↓ +自己的数据库 + ↓ +自己的 Queue + ↓ +自己的 Auth + ↓ +自己的 EventBus + ↓ +自己的 Task System + +除非明确声明为 external service,并通过标准 Adapter 接入。 + +--- + +# 3. Plugin 的本质 + +Plugin 是: + +```text +Extension Package ++ +Manifest ++ +Runtime ++ +Capabilities ++ +UI ++ +Configuration +```` + +例如 SEO Plugin: + +```text +seo.plugin +├── Resource +│ ├── seo.website +│ ├── seo.keyword +│ └── seo.article +│ +├── Action +│ ├── seo.website.scan +│ ├── seo.keyword.research +│ └── seo.article.generate +│ +├── Skill +│ ├── seo-audit +│ └── content-generation +│ +├── MCP +│ ├── search-engine +│ └── browser +│ +├── Workflow +│ └── seo-audit-workflow +│ +├── Event +│ ├── seo.website.scanned +│ └── seo.article.generated +│ +└── UI + ├── Website + ├── Keywords + ├── Articles + └── Settings +``` + +--- + +# 4. Plugin Namespace + +每个 Plugin 必须拥有唯一 namespace。 + +格式: + +```text +. +``` + +例如: + +```text +devos.seo +devos.devops +devos.crm +github.integration +cloudflare.integration +``` + +Plugin 内部 Resource: + +```text +devos.seo.website +devos.seo.keyword +``` + +Action: + +```text +devos.seo.website.scan +``` + +Skill: + +```text +devos.seo.audit +``` + +禁止两个 Plugin 注册同一个 namespace。 + +--- + +# 5. Plugin ID + +Plugin ID: + +```ts +type PluginId = string +``` + +例如: + +```text +devos.seo +``` + +必须满足: + +```text +^[a-z0-9][a-z0-9._-]*$ +``` + +--- + +# 6. Plugin Manifest + +每个 Plugin 必须提供: + +```text +plugin.json +``` + +推荐: + +```json +{ + "id": "devos.seo", + "name": "SEO", + "version": "1.0.0", + "description": "SEO automation capabilities", + "runtime": "devos", + "apiVersion": "1", + "author": "DevOS", + "license": "MIT" +} +``` + +--- + +# 7. 完整 Manifest + +```ts +interface PluginManifest { + id: string + + name: string + + version: string + + description?: string + + apiVersion: string + + runtime: 'devos' + + author?: string + + homepage?: string + + repository?: string + + license?: string + + icon?: string + + categories?: string[] + + dependencies?: PluginDependency[] + + optionalDependencies?: PluginDependency[] + + permissions?: PluginPermission[] + + capabilities?: PluginCapabilityDeclaration[] + + resources?: PluginResourceDeclaration[] + + actions?: PluginActionDeclaration[] + + skills?: PluginSkillDeclaration[] + + mcp?: PluginMCPDeclaration[] + + workflows?: PluginWorkflowDeclaration[] + + events?: PluginEventDeclaration[] + + ui?: PluginUIDeclaration[] + + settings?: PluginSettingDeclaration[] + + workers?: PluginWorkerDeclaration[] +} +``` + +--- + +# 8. Plugin 生命周期 + +Plugin 状态: + +```text +discovered + ↓ +installing + ↓ +installed + ↓ +configuring + ↓ +enabled + ↓ +running + ↓ +disabled + ↓ +uninstalling + ↓ +uninstalled +``` + +异常: + +```text +install_failed +activation_failed +runtime_error +upgrade_failed +``` + +--- + +# 9. Plugin Runtime 状态 + +```ts +type PluginStatus = + | 'discovered' + | 'installing' + | 'installed' + | 'configuring' + | 'enabled' + | 'running' + | 'disabled' + | 'uninstalling' + | 'uninstalled' + | 'install_failed' + | 'activation_failed' + | 'runtime_error' + | 'upgrade_failed' +``` + +--- + +# 10. Plugin Resource + +Plugin 本身必须成为 DevOS Resource: + +```text +core.plugin +``` + +Plugin Resource: + +```text +core.plugin.installation +``` + +--- + +# 11. Plugin Actions + +至少: + +```text +core.plugin.install +core.plugin.uninstall +core.plugin.enable +core.plugin.disable +core.plugin.restart +core.plugin.upgrade +core.plugin.configure +core.plugin.health +core.plugin.reload +``` + +--- + +# 12. 所有 Plugin 管理操作必须走 Action Runtime + +错误: + +```text +POST /plugins/:id/enable + +controller: + plugin.enable() +``` + +正确: + +```text +HTTP + ↓ +core.plugin.enable + ↓ +Action Runtime + ↓ +Plugin Runtime +``` + +CLI: + +```text +devos plugin enable devos.seo +``` + +也必须: + +```text +CLI + ↓ +Action Runtime + ↓ +core.plugin.enable +``` + +Agent: + +```text +Agent + ↓ +core.plugin.enable + ↓ +Action Runtime +``` + +三者执行路径必须完全一致。 + +--- + +# 13. Plugin Installation Record + +数据库: + +```ts +interface PluginInstallation { + id: string + + pluginId: string + + version: string + + status: PluginStatus + + source: PluginSource + + enabled: boolean + + installedAt: Date + + updatedAt: Date + + activatedAt?: Date + + disabledAt?: Date + + error?: string + + metadata?: Record +} +``` + +--- + +# 14. Plugin Source + +支持: + +```ts +type PluginSource = + | { + type: 'builtin' + } + | { + type: 'local' + path: string + } + | { + type: 'package' + package: string + version?: string + } + | { + type: 'git' + repository: string + ref?: string + } + | { + type: 'url' + url: string + } +``` + +第一阶段至少实现: + +```text +builtin +local +package +``` + +Git / URL 可以作为后续扩展。 + +--- + +# 15. Built-in Plugin + +DevOS 自己的功能也可以 Plugin 化。 + +例如: + +```text +devos.core +devos.seo +devos.devops +``` + +但 Core Runtime 本身不能依赖 Plugin Runtime 才能启动。 + +即: + +```text +Core Runtime + ↓ +Plugin Runtime + ↓ +Optional Plugins +``` + +而不是: + +```text +Plugin Runtime + ↓ +Core Runtime +``` + +--- + +# 16. Plugin Registration + +Plugin 激活后: + +```text +Plugin + ↓ +Manifest + ↓ +Validate + ↓ +Register + ├── Resources + ├── Actions + ├── Capabilities + ├── Skills + ├── MCP + ├── Events + ├── Workflows + └── UI +``` + +--- + +# 17. Plugin Registry + +实现: + +```ts +interface PluginRegistry { + register(plugin: RegisteredPlugin): Promise + + unregister(pluginId: string): Promise + + get(pluginId: string): RegisteredPlugin | undefined + + list(): RegisteredPlugin[] + + has(pluginId: string): boolean +} +``` + +--- + +# 18. Registered Plugin + +```ts +interface RegisteredPlugin { + manifest: PluginManifest + + status: PluginStatus + + runtime: PluginRuntime + + registeredAt: Date +} +``` + +--- + +# 19. Plugin Runtime + +```ts +interface PluginRuntime { + initialize(context: PluginContext): Promise + + activate(context: PluginContext): Promise + + deactivate(context: PluginContext): Promise + + dispose(context: PluginContext): Promise + + health(): Promise +} +``` + +--- + +# 20. Plugin Context + +```ts +interface PluginContext { + pluginId: string + + version: string + + logger: Logger + + eventBus: EventBus + + resourceRegistry: ResourceRegistry + + actionRegistry: ActionRegistry + + capabilityRegistry: CapabilityRegistry + + skillRegistry: SkillRegistry + + mcpRegistry: MCPRegistry + + config: PluginConfigService + + storage: PluginStorage + + signal: AbortSignal +} +``` + +Plugin 不应该直接拿: + +```text +PrismaClient +RedisClient +BullMQ +``` + +Plugin 应该使用 DevOS 提供的抽象。 + +--- + +# 21. Plugin Storage + +某些 Plugin 需要自己的持久化数据。 + +提供: + +```ts +interface PluginStorage { + get(key: string): Promise + + set(key: string, value: T): Promise + + delete(key: string): Promise +} +``` + +但这是: + +> Plugin Storage + +不是: + +> Plugin 自己拥有一套数据库系统。 + +--- + +# 22. Plugin Database + +如果 Plugin 需要复杂业务数据: + +必须通过 DevOS Database / ORM / Migration Runtime。 + +例如: + +```text +packages/plugins/seo + migrations/ + schema/ +``` + +数据库表必须带 Plugin Namespace。 + +例如: + +```text +seo_websites +seo_keywords +seo_articles +``` + +禁止 Plugin 私自建立第二个 PostgreSQL 实例。 + +--- + +# 23. Plugin Configuration + +Plugin 可以声明 Settings。 + +例如: + +```json +{ + "settings": [ + { + "key": "defaultModel", + "type": "string", + "required": true + }, + { + "key": "apiEndpoint", + "type": "url" + } + ] +} +``` + +--- + +# 24. Plugin Setting Schema + +```ts +interface PluginSettingDeclaration { + key: string + + type: + | 'string' + | 'number' + | 'boolean' + | 'secret' + | 'url' + | 'select' + | 'multiselect' + | 'json' + + label: string + + description?: string + + required?: boolean + + default?: unknown + + options?: { + label: string + value: string + }[] +} +``` + +--- + +# 25. Plugin Settings Resource + +Plugin 配置应该属于: + +```text +core.plugin.settings +``` + +而不是: + +```text +plugin_database_table +``` + +API: + +```text +GET +/api/plugins/:pluginId/settings + +PUT +/api/plugins/:pluginId/settings +``` + +但是最终执行: + +```text +core.plugin.configure +``` + +--- + +# 26. Secret Settings + +例如: + +```text +OpenAI API Key +Cloudflare API Token +GitHub Token +SMTP Password +``` + +必须使用: + +```text +type = secret +``` + +数据库不得明文保存。 + +推荐: + +```text +Encryption at Rest +``` + +读取时默认: + +```text +******** +``` + +只有真正执行需要时才能在 Runtime 内解密。 + +--- + +# 27. Plugin Settings 权限 + +必须区分: + +```text +plugin.view +plugin.configure +plugin.install +plugin.uninstall +plugin.enable +plugin.disable +``` + +普通用户: + +```text +plugin.view +``` + +管理员: + +```text +plugin.configure +``` + +系统管理员: + +```text +plugin.install +plugin.uninstall +``` + +具体策略由 RBAC / Policy Runtime 控制。 + +--- + +# 28. Plugin UI + +Plugin 可以提供自己的页面。 + +例如: + +```text +SEO +├── Overview +├── Websites +├── Keywords +├── Articles +├── Tasks +└── Settings +``` + +Plugin UI 不是独立 SPA。 + +必须挂载到: + +```text +DevOS UI Shell +``` + +--- + +# 29. Plugin UI Manifest + +```ts +interface PluginUIDeclaration { + routes?: PluginRoute[] + + navigation?: PluginNavigationItem[] + + dashboards?: PluginDashboard[] + + widgets?: PluginWidget[] + + settingsPage?: boolean +} +``` + +--- + +# 30. Plugin Route + +```ts +interface PluginRoute { + id: string + + path: string + + title: string + + component: string + + icon?: string + + permissions?: string[] +} +``` + +例如: + +```json +{ + "id": "seo-websites", + "path": "/seo/websites", + "title": "Websites", + "component": "SeoWebsitesPage", + "permissions": [ + "devos.seo.website.read" + ] +} +``` + +--- + +# 31. Plugin Navigation + +Plugin 可以向左侧导航注册: + +```text +SEO + Overview + Websites + Keywords + Articles + Tasks +``` + +但不能直接修改 DevOS Shell。 + +必须: + +```text +Plugin + ↓ +Navigation Registry + ↓ +UI Shell +``` + +--- + +# 32. Navigation Registry + +```ts +interface NavigationRegistry { + register(item: NavigationItem): void + + unregister(pluginId: string): void + + list(context: NavigationContext): NavigationItem[] +} +``` + +必须根据: + +```text +permission +organization +project +plugin enabled +``` + +动态过滤。 + +--- + +# 33. Plugin Dashboard + +Plugin 可以提供 Dashboard: + +```text +SEO Overview + +Websites: 127 +Keywords: 3,821 +Articles: 1,240 +Tasks Running: 17 +Errors: 3 +``` + +Dashboard 只负责: + +```text +展示 +查询 +触发 Action +``` + +不能在 UI 内实现业务逻辑。 + +--- + +# 34. Plugin Widget + +Plugin 可以注册: + +```text +Dashboard Widget +Chat Widget +Task Widget +Resource Widget +Report Widget +``` + +例如: + +```text +SEO Health Score +``` + +Widget 可以声明: + +```ts +interface PluginWidget { + id: string + + title: string + + component: string + + size: 'small' | 'medium' | 'large' + + permissions?: string[] +} +``` + +--- + +# 35. Plugin Page 与 Action Runtime + +页面: + +```text +按钮:Scan Website +``` + +不能: + +```ts +fetch('/seo/scan') +``` + +应该: + +```text +UI + ↓ +Action Client + ↓ +devos.seo.website.scan + ↓ +Action Runtime +``` + +--- + +# 36. Plugin Resource UI + +如果 Plugin 注册: + +```text +seo.website +``` + +可以自动获得: + +```text +List +Detail +Create +Edit +Delete +``` + +如果 Resource 声明: + +```text +ui.list +ui.detail +``` + +DevOS Generic UI 可以自动生成。 + +Plugin 只需要实现复杂页面。 + +--- + +# 37. Plugin Actions + +Plugin Action: + +```ts +interface PluginActionDeclaration { + id: string + + name: string + + description?: string + + inputSchema: unknown + + outputSchema: unknown + + mode: 'sync' | 'async' | 'stream' + + permissions: string[] + + requiresApproval?: boolean +} +``` + +Action 最终进入: + +```text +Action Registry +``` + +--- + +# 38. Plugin Capability + +Plugin Action 自动成为 Capability。 + +例如: + +```text +devos.seo.website.scan +``` + +注册: + +```text +Capability + type = action + source = plugin +``` + +Agent 就能够发现。 + +--- + +# 39. Plugin Skill + +Plugin 可以注册 Skill: + +```ts +interface PluginSkillDeclaration { + id: string + + name: string + + description: string + + version: string + + instructions: string + + requiredCapabilities: string[] + + inputSchema?: unknown + + outputSchema?: unknown +} +``` + +--- + +# 40. Plugin 与 Agent + +例如: + +```text +SEO Plugin + ↓ +Skill: +seo.audit + ↓ +Capabilities: +seo.website.scan +seo.keyword.research +seo.article.generate + ↓ +Agent +``` + +Agent 不需要知道: + +```text +这个能力来自哪个数据库 +哪个 Controller +哪个 Plugin 文件 +``` + +只看到: + +```text +Capability +``` + +--- + +# 41. Plugin MCP + +Plugin 可以声明 MCP: + +```ts +interface PluginMCPDeclaration { + id: string + + name: string + + transport: + | 'stdio' + | 'http' + | 'sse' + + endpoint?: string + + command?: string + + args?: string[] +} +``` + +但是: + +**MCP 仍然必须通过 MCP Runtime + Action Runtime。** + +--- + +# 42. Plugin Event + +Plugin 可以声明 Event: + +```text +devos.seo.website.scanned +devos.seo.article.generated +``` + +Event 进入: + +```text +Event Registry +``` + +并可以被: + +```text +Agent +Workflow +Notification +Webhook +Plugin +``` + +消费。 + +--- + +# 43. Plugin Event Handler + +Plugin Handler: + +```text +Event + ↓ +Plugin Handler + ↓ +Action Runtime +``` + +禁止: + +```text +Event + ↓ +Plugin Handler + ↓ +直接 DB mutation +``` + +--- + +# 44. Plugin Workflow + +Plugin 可以提供 Workflow: + +```text +seo.full.audit +``` + +例如: + +```text +scan website + ↓ +collect keywords + ↓ +analyze pages + ↓ +generate report +``` + +Workflow 由: + +```text +Action +Task +Job +``` + +组成。 + +--- + +# 45. Plugin Scheduler + +Plugin 可以注册 Schedule Definition。 + +例如: + +```text +SEO daily scan +Every day at 03:00 +``` + +最终还是: + +```text +Scheduler + ↓ +Task + ↓ +Action +``` + +Plugin 不得自己运行: + +```text +setInterval() +``` + +或: + +```text +node-cron +``` + +来承担业务调度。 + +--- + +# 46. Plugin Worker + +某些 Plugin 可能需要特殊 Worker。 + +例如: + +```text +browser +ffmpeg +docker +ssh +``` + +Plugin 可以声明 Worker Capability: + +```ts +interface PluginWorkerDeclaration { + id: string + + queues: string[] + + capabilities: string[] + + concurrency?: number +} +``` + +最终由: + +```text +Worker Runtime +``` + +管理。 + +--- + +# 47. Plugin Dependencies + +例如: + +```json +{ + "dependencies": [ + { + "id": "devos.browser", + "version": "^1.0.0" + } + ] +} +``` + +安装时: + +```text +Plugin A + ↓ +Dependency Resolver + ↓ +Plugin B + ↓ +Install +``` + +--- + +# 48. Dependency Version + +必须支持: + +```text +exact +range +``` + +例如: + +```text +1.2.3 +^1.2.0 +>=1.0.0 <2.0.0 +``` + +--- + +# 49. Dependency Graph + +Plugin Runtime 必须检测: + +```text +A → B +B → C +C → A +``` + +发现: + +```text +circular dependency +``` + +直接拒绝安装。 + +--- + +# 50. Plugin API Version + +Plugin 必须声明: + +```text +apiVersion +``` + +例如: + +```text +apiVersion = 1 +``` + +DevOS Runtime 升级: + +```text +API v1 +API v2 +``` + +可以兼容旧 Plugin。 + +--- + +# 51. Plugin Compatibility + +安装之前必须执行: + +```text +Manifest + ↓ +API Compatibility + ↓ +Dependency Compatibility + ↓ +Permission Validation + ↓ +Resource Conflict Check + ↓ +Action Conflict Check + ↓ +Install +``` + +--- + +# 52. Resource Conflict + +例如: + +Plugin A: + +```text +seo.website +``` + +Plugin B: + +```text +seo.website +``` + +必须拒绝: + +```text +RESOURCE_NAMESPACE_CONFLICT +``` + +除非明确声明: + +```text +override +``` + +第一阶段: + +**禁止 Override。** + +--- + +# 53. Action Conflict + +同样: + +```text +seo.website.scan +``` + +只能由一个 Plugin 注册。 + +--- + +# 54. Capability Conflict + +Capability ID 也必须唯一。 + +--- + +# 55. Plugin Enable + +Enable: + +```text +core.plugin.enable + ↓ +Load Plugin + ↓ +Validate + ↓ +Register + ↓ +Activate + ↓ +Health Check + ↓ +enabled +``` + +如果失败: + +```text +activation_failed +``` + +不得标记为 enabled。 + +--- + +# 56. Plugin Disable + +Disable: + +```text +core.plugin.disable + ↓ +Stop accepting new work + ↓ +Drain active work + ↓ +Deactivate + ↓ +Unregister runtime capabilities + ↓ +disabled +``` + +已经运行中的 Task: + +```text +默认继续完成 +``` + +除非 Plugin 声明: + +```text +shutdownPolicy = cancel +``` + +--- + +# 57. Plugin Uninstall + +不能直接删除。 + +必须: + +```text +Disable + ↓ +Check Running Tasks + ↓ +Check Dependencies + ↓ +Check Data Policy + ↓ +Unregister + ↓ +Remove +``` + +--- + +# 58. Plugin Data Policy + +Manifest 可以声明: + +```ts +dataPolicy: { + preserveOnDisable: boolean + + preserveOnUninstall: boolean + + destructiveUninstall: boolean +} +``` + +默认: + +```text +preserveOnUninstall = true +``` + +即: + +**卸载 Plugin 默认不删除业务数据。** + +--- + +# 59. Plugin Upgrade + +升级流程: + +```text +Current Plugin + ↓ +Read New Manifest + ↓ +Compatibility Check + ↓ +Dependency Check + ↓ +Migration Plan + ↓ +Backup / Safety Check + ↓ +Disable + ↓ +Migration + ↓ +Install New Version + ↓ +Register + ↓ +Activate + ↓ +Health Check +``` + +--- + +# 60. Migration + +Plugin Migration: + +```ts +interface PluginMigration { + from: string + + to: string + + up(): Promise + + down?(): Promise +} +``` + +Migration 必须支持: + +```text +version history +``` + +--- + +# 61. Upgrade Failure + +升级失败必须: + +```text +upgrade_failed +``` + +并尽可能: + +```text +Rollback +``` + +但不要假设所有 Migration 都可以自动 Rollback。 + +因此: + +```text +backup ++ +forward migration ++ +recovery procedure +``` + +必须存在。 + +--- + +# 62. Plugin Isolation + +Plugin 必须受到: + +```text +Permission +Namespace +Resource Scope +Action Scope +``` + +限制。 + +Plugin 不应该默认拥有: + +```text +root filesystem +all environment variables +all secrets +all database tables +``` + +--- + +# 63. Plugin Permission Declaration + +Manifest: + +```json +{ + "permissions": [ + "network:http", + "storage:plugin", + "secret:seo-api", + "resource:seo.website" + ] +} +``` + +Permission 必须经过用户/管理员批准。 + +--- + +# 64. Permission 分类 + +至少: + +```text +resource +action +network +storage +secret +filesystem +process +worker +mcp +``` + +--- + +# 65. Network Permission + +Plugin 不应该默认访问任意互联网地址。 + +推荐: + +```text +network:http +network:https +``` + +未来可以限制: + +```text +network:domain:api.example.com +``` + +--- + +# 66. Secret Permission + +Plugin 请求: + +```text +secret:openai +``` + +只能访问: + +```text +OpenAI Credential +``` + +不能读取: + +```text +Cloudflare Credential +GitHub Credential +``` + +--- + +# 67. Plugin Credential + +统一使用: + +```text +Credential Runtime +``` + +例如: + +```text +core.credential +``` + +Plugin: + +```text +Credential Request + ↓ +Permission + ↓ +Credential Runtime + ↓ +Secret +``` + +Plugin 不应该直接读取 `.env`。 + +--- + +# 68. Plugin Environment + +Plugin 可以获得: + +```ts +interface PluginEnvironment { + devosVersion: string + + pluginId: string + + pluginVersion: string + + environment: 'development' | 'test' | 'production' +} +``` + +禁止直接依赖大量 DevOS 内部环境变量。 + +--- + +# 69. Plugin Logging + +Plugin 必须使用: + +```ts +context.logger +``` + +例如: + +```ts +context.logger.info( + 'SEO scan started', + { + websiteId + } +) +``` + +日志自动获得: + +```text +pluginId +correlationId +executionId +taskId +``` + +--- + +# 70. Plugin Events + +Plugin 必须使用: + +```ts +context.eventBus.publish(...) +``` + +Event 自动补充: + +```text +pluginId +``` + +--- + +# 71. Plugin Health + +```ts +interface PluginHealth { + status: + | 'healthy' + | 'degraded' + | 'unhealthy' + + message?: string + + checks?: HealthCheck[] +} +``` + +例如: + +```text +SEO Plugin + ├── Database healthy + ├── Search API healthy + ├── Browser MCP degraded + └── AI Provider healthy +``` + +--- + +# 72. Plugin Health Event + +自动产生: + +```text +plugin.health.changed +plugin.health.failed +plugin.health.recovered +``` + +--- + +# 73. Plugin Observability + +Plugin 的: + +```text +Action +Task +Job +Execution +Event +Log +Audit +Trace +Metric +``` + +全部自动带: + +```text +pluginId +``` + +这样可以统计: + +```text +Plugin usage +Plugin errors +Plugin latency +Plugin cost +Plugin health +``` + +--- + +# 74. Plugin Metrics + +自动生成: + +```text +devos_plugin_action_total +devos_plugin_error_total +devos_plugin_execution_duration_ms +devos_plugin_task_total +devos_plugin_mcp_request_total +devos_plugin_cost_total +``` + +--- + +# 75. Plugin Audit + +例如: + +```text +plugin.installed +plugin.enabled +plugin.disabled +plugin.upgraded +plugin.uninstalled +plugin.configured +``` + +都必须产生 Audit。 + +例如: + +```text +Admin Alice + ↓ +core.plugin.enable + ↓ +devos.seo + ↓ +SUCCESS +``` + +--- + +# 76. Plugin UI Permission + +Plugin 页面不能因为已经加载就绕过权限。 + +例如: + +```text +SEO Settings +``` + +必须: + +```text +plugin.view ++ +plugin.configure +``` + +--- + +# 77. Plugin Dynamic UI + +前端需要: + +```text +Plugin Manifest + ↓ +UI Registry + ↓ +Route Registry + ↓ +Navigation Registry + ↓ +Dynamic Module +``` + +--- + +# 78. Frontend Plugin Package + +推荐: + +```text +packages/plugins/seo/ +├── manifest.ts +├── backend/ +│ ├── index.ts +│ ├── resources/ +│ ├── actions/ +│ ├── skills/ +│ ├── mcp/ +│ └── migrations/ +│ +└── frontend/ + ├── index.ts + ├── routes/ + ├── pages/ + ├── widgets/ + └── components/ +``` + +--- + +# 79. Plugin Frontend Contract + +Plugin Frontend 不应该: + +```text +import backend database +import Prisma +import Redis +``` + +只能使用: + +```text +Action Client +Resource API +Query Client +UI SDK +``` + +--- + +# 80. Plugin UI SDK + +DevOS 应提供: + +```ts +interface DevOSPluginUI { + registerRoute(...) + + registerNavigation(...) + + registerWidget(...) + + registerDashboard(...) + + registerSettings(...) +} +``` + +--- + +# 81. Plugin Action Client + +前端: + +```ts +await devos.actions.execute( + 'devos.seo.website.scan', + { + websiteId + } +) +``` + +而不是: + +```ts +fetch('/api/seo/scan') +``` + +--- + +# 82. Plugin Resource Client + +```ts +const websites = + await devos.resources.list( + 'devos.seo.website' + ) +``` + +--- + +# 83. Plugin Task UI + +异步 Action 返回: + +```ts +{ + taskId: 'task_123' +} +``` + +前端自动进入: + +```text +Task Detail +``` + +可以显示: + +```text +Progress +Jobs +Logs +Events +Execution +Result +``` + +--- + +# 84. Plugin Chat Integration + +Plugin 可以向 Agent Chat 注册: + +```text +context action +``` + +例如用户打开: + +```text +Website: example.com +``` + +Chat: + +```text +Ask Agent about this website +``` + +Agent 自动获得: + +```text +resource = devos.seo.website +resourceId = website_123 +``` + +--- + +# 85. Plugin Context Provider + +```ts +interface PluginContextProvider { + getContext( + resource: ResourceReference + ): Promise +} +``` + +这样 Agent 可以理解: + +```text +当前页面 +当前 Resource +当前 Project +当前 Task +``` + +--- + +# 86. Plugin Report + +Plugin 可以注册 Report: + +```text +SEO Audit Report +Server Deployment Report +CRM Customer Report +``` + +Report 应该: + +```text +Task + ↓ +Action + ↓ +Artifact + ↓ +Report +``` + +--- + +# 87. Plugin Artifact + +Plugin 可以生成: + +```text +PDF +CSV +JSON +HTML +Markdown +Image +Archive +``` + +统一进入: + +```text +core.artifact +``` + +而不是 Plugin 自己管理下载系统。 + +--- + +# 88. Plugin API + +Plugin 可以提供 API,但 API 只是入口。 + +例如: + +```http +POST /api/plugins/seo/scan +``` + +内部: + +```text +HTTP + ↓ +Action Resolver + ↓ +devos.seo.website.scan + ↓ +Action Runtime +``` + +不能: + +```text +Controller + ↓ +Plugin Handler + ↓ +DB +``` + +--- + +# 89. Plugin Webhook + +Plugin 可以声明: + +```text +incoming webhook +``` + +例如: + +```text +POST /api/plugins/github/webhook +``` + +流程: + +```text +Webhook + ↓ +Verify + ↓ +Normalize + ↓ +Event + ↓ +Task / Action +``` + +--- + +# 90. Plugin Export / Import + +Plugin 配置可以导出: + +```json +{ + "pluginId": "devos.seo", + "version": "1.2.0", + "settings": { + "defaultModel": "..." + } +} +``` + +Secret 不得导出明文。 + +--- + +# 91. Plugin Backup + +升级 / 卸载前可以: + +```text +Plugin Data +Plugin Settings +Plugin Metadata +``` + +生成: + +```text +core.artifact +``` + +作为恢复点。 + +--- + +# 92. Plugin Marketplace + +未来可以实现: + +```text +Plugin Marketplace +``` + +但 Marketplace 不是 Runtime。 + +Runtime 只负责: + +```text +Discover +Install +Verify +Load +Activate +Disable +Upgrade +Uninstall +``` + +Marketplace 负责: + +```text +Search +Rating +Description +Version +Download +``` + +--- + +# 93. Plugin Signature + +未来 Plugin 可以支持: + +```text +package signature +``` + +安装流程: + +```text +Download + ↓ +Verify Signature + ↓ +Verify Checksum + ↓ +Compatibility + ↓ +Install +``` + +第一阶段可以先实现: + +```text +checksum +``` + +--- + +# 94. Plugin Trust Level + +定义: + +```ts +type PluginTrust = + | 'builtin' + | 'trusted' + | 'verified' + | 'community' + | 'untrusted' +``` + +不同 Trust Level 可以有不同权限。 + +--- + +# 95. Plugin Sandbox + +第一阶段: + +```text +Process-level isolation +``` + +高级版本: + +```text +Container +Worker +Sandbox +``` + +但不应该一开始为了“安全”把所有 Plugin 都设计成复杂微服务。 + +优先保证: + +```text +Permission +Credential Isolation +Namespace Isolation +Runtime Isolation +``` + +--- + +# 96. Plugin Crash Isolation + +Plugin 激活失败: + +```text +devos.seo + ↓ +activation_failed +``` + +不能导致: + +```text +DevOS Core +``` + +整体无法启动。 + +启动策略: + +```text +Core starts + ↓ +Load Plugins + ↓ +Plugin A success +Plugin B failed +Plugin C success + ↓ +DevOS remains available +``` + +--- + +# 97. Plugin Startup + +启动: + +```text +DevOS Boot + ↓ +Core Runtime + ↓ +Database + ↓ +Redis + ↓ +Event Runtime + ↓ +Task Runtime + ↓ +Action Runtime + ↓ +Plugin Runtime + ↓ +Load Plugins + ↓ +Health Checks + ↓ +Ready +``` + +--- + +# 98. Plugin Shutdown + +关闭: + +```text +Stop accepting new requests + ↓ +Scheduler pause + ↓ +Plugin workers drain + ↓ +Plugin tasks finish + ↓ +Deactivate plugins + ↓ +Close Event subscriptions + ↓ +Close connections + ↓ +Shutdown Core +``` + +--- + +# 99. Plugin Dependency Startup + +如果: + +```text +A → B +``` + +启动顺序: + +```text +B + ↓ +A +``` + +关闭: + +```text +A + ↓ +B +``` + +Dependency Resolver 必须负责排序。 + +--- + +# 100. Plugin Registry 与其他 Registry + +最终: + +```text +Plugin Registry + │ + ├── Resource Registry + ├── Action Registry + ├── Capability Registry + ├── Skill Registry + ├── MCP Registry + ├── Event Registry + ├── Navigation Registry + ├── Widget Registry + └── Workflow Registry +``` + +Plugin 是: + +> Registry 的扩展来源。 + +不是: + +> Registry 的替代品。 + +--- + +# 101. Plugin 完整模型 + +最终: + +```text +Plugin +│ +├── Manifest +│ +├── Resources +│ +├── Actions +│ +├── Capabilities +│ +├── Skills +│ +├── MCP +│ +├── Workflows +│ +├── Events +│ +├── Scheduler +│ +├── Workers +│ +├── Settings +│ +├── Credentials +│ +├── UI +│ ├── Routes +│ ├── Navigation +│ ├── Dashboard +│ └── Widgets +│ +└── Runtime + ├── Lifecycle + ├── Health + ├── Logging + ├── Metrics + └── Tracing +``` + +--- + +# 102. Plugin Runtime 与 DevOS 的最终关系 + +```text + DevOS + │ + ┌───────┴────────┐ + │ │ + Core Runtime Plugin Runtime + │ + ┌──────────────────────┼─────────────────────┐ + ↓ ↓ ↓ + Plugin A Plugin B Plugin C + │ │ │ + Resource Resource Resource + Action Action Action + Skill Skill Skill + MCP MCP MCP + UI UI UI +``` + +所有 Plugin 最终进入: + +```text +DevOS Runtime +``` + +--- + +# 103. SEO Plugin 示例 + +SEO 不应该成为第二套系统。 + +应该: + +```text +DevOS + │ + └── Plugin: devos.seo +``` + +提供: + +```text +Resources: + devos.seo.website + devos.seo.keyword + devos.seo.article + devos.seo.backlink + devos.seo.campaign + +Actions: + devos.seo.website.scan + devos.seo.keyword.research + devos.seo.article.generate + devos.seo.backlink.find + devos.seo.campaign.run + +Skills: + devos.seo.audit + devos.seo.content + devos.seo.link-building + +MCP: + search + browser + cms + backlink providers + +UI: + SEO Dashboard + Websites + Keywords + Content + Backlinks + Campaigns + Settings +``` + +--- + +# 104. Agent 使用 Plugin + +用户: + +> 给 example.com 做完整 SEO 审计。 + +Agent: + +```text +Goal + ↓ +Capability Discovery + ↓ +devos.seo.audit Skill + ↓ +Capabilities + ├── website.scan + ├── keyword.research + ├── page.analyze + └── report.generate + ↓ +Task + ↓ +Jobs + ↓ +Actions + ↓ +Execution + ↓ +Events + ↓ +Agent Observation +``` + +Agent 不需要直接知道: + +```text +SEO Plugin 内部代码 +``` + +--- + +# 105. Plugin 与独立 Backend + +DevOS 必须支持两种模式。 + +## Mode A + +```text +DevOS + ↓ +Plugin + ↓ +Domain +``` + +推荐用于: + +```text +SEO +CRM +Content +Marketing +DevOps +``` + +--- + +## Mode B + +```text +DevOS Minimal Core + ↓ +Fork + ↓ +Independent Application +``` + +例如: + +```text +DevOS Starter + ↓ +Fork + ↓ +Custom Product +``` + +独立项目仍然可以保留: + +```text +Identity +RBAC +Resource +Action +Task +Event +Audit +Observability +``` + +但删除不需要的 Plugin。 + +--- + +# 106. Plugin 不等于 Microservice + +不要把: + +```text +Plugin +``` + +自动理解成: + +```text +Microservice +``` + +默认: + +```text +Plugin = In-process Extension +``` + +只有明确需要: + +```text +isolation +resource-heavy worker +different runtime +different deployment lifecycle +``` + +才使用: + +```text +External Service +``` + +--- + +# 107. External Plugin + +未来支持: + +```text +DevOS + ↓ +External Plugin Adapter + ↓ +HTTP / gRPC / MCP + ↓ +External Service +``` + +但外部 Plugin 仍然暴露: + +```text +Resource +Action +Capability +Skill +Event +UI +``` + +给 DevOS。 + +--- + +# 108. Plugin Adapter + +```ts +interface PluginAdapter { + install(): Promise + + enable(): Promise + + disable(): Promise + + uninstall(): Promise + + health(): Promise +} +``` + +--- + +# 109. Plugin Runtime API + +建议统一: + +```ts +interface DevOSPlugin { + manifest: PluginManifest + + initialize(context: PluginContext): Promise + + activate(context: PluginContext): Promise + + deactivate(context: PluginContext): Promise + + dispose(context: PluginContext): Promise +} +``` + +--- + +# 110. Package Architecture + +Zcode 必须实现: + +```text +packages/ +└── plugin/ + ├── types/ + │ ├── manifest.ts + │ ├── lifecycle.ts + │ └── permission.ts + │ + ├── registry/ + │ └── plugin-registry.ts + │ + ├── runtime/ + │ ├── plugin-runtime.ts + │ ├── lifecycle.ts + │ ├── loader.ts + │ ├── activator.ts + │ └── disposer.ts + │ + ├── installer/ + │ ├── installer.ts + │ ├── resolver.ts + │ ├── validator.ts + │ └── checksum.ts + │ + ├── configuration/ + │ ├── config-service.ts + │ └── secret-service.ts + │ + ├── isolation/ + │ ├── permissions.ts + │ └── credentials.ts + │ + ├── health/ + │ └── health-service.ts + │ + └── ui/ + ├── route-registry.ts + ├── navigation-registry.ts + ├── widget-registry.ts + └── dashboard-registry.ts +``` + +--- + +# 111. Backend Plugin Example + +```text +plugins/ +└── seo/ + ├── plugin.json + ├── index.ts + │ + ├── resources/ + │ ├── website.ts + │ ├── keyword.ts + │ └── article.ts + │ + ├── actions/ + │ ├── scan.ts + │ ├── research.ts + │ └── generate.ts + │ + ├── skills/ + │ ├── seo-audit.ts + │ └── content.ts + │ + ├── mcp/ + │ └── browser.ts + │ + ├── events/ + │ └── definitions.ts + │ + ├── workflows/ + │ └── audit.ts + │ + ├── migrations/ + │ + └── frontend/ + ├── routes/ + ├── pages/ + ├── widgets/ + └── index.ts +``` + +--- + +# 112. Plugin Test + +每个 Plugin 必须提供: + +```text +manifest test +lifecycle test +registration test +permission test +configuration test +action test +event test +health test +ui registration test +upgrade test +uninstall test +``` + +--- + +# 113. Acceptance Criteria + +## Plugin Lifecycle + +* [ ] Discover +* [ ] Install +* [ ] Configure +* [ ] Enable +* [ ] Disable +* [ ] Restart +* [ ] Upgrade +* [ ] Uninstall +* [ ] Health + +## Registry + +* [ ] Plugin Registry +* [ ] Resource registration +* [ ] Action registration +* [ ] Capability registration +* [ ] Skill registration +* [ ] MCP registration +* [ ] Event registration +* [ ] Workflow registration +* [ ] UI registration + +## Security + +* [ ] Permission declaration +* [ ] Permission approval +* [ ] Credential isolation +* [ ] Secret isolation +* [ ] Namespace isolation +* [ ] Network policy +* [ ] Sensitive data redaction + +## UI + +* [ ] Dynamic routes +* [ ] Navigation +* [ ] Settings page +* [ ] Dashboard +* [ ] Widgets +* [ ] Resource pages +* [ ] Action buttons +* [ ] Task integration + +## Runtime + +* [ ] Logger +* [ ] Metrics +* [ ] Trace +* [ ] Event +* [ ] Health +* [ ] Task +* [ ] Worker +* [ ] Scheduler + +--- + +# 114. Integration Test + +必须测试: + +```text +Install Plugin + ↓ +Manifest Validation + ↓ +Register Resource + ↓ +Register Action + ↓ +Register Skill + ↓ +Register MCP + ↓ +Register Event + ↓ +Register UI + ↓ +Enable + ↓ +Health Check +``` + +最终: + +```text +Plugin = healthy +``` + +--- + +# 115. Disable Test + +```text +Plugin enabled + ↓ +Task running + ↓ +Disable + ↓ +Drain + ↓ +Deactivate + ↓ +Unregister + ↓ +Plugin disabled +``` + +验证: + +```text +Existing Task +``` + +不会被无故破坏。 + +--- + +# 116. Permission Test + +Plugin 尝试: + +```text +read secret:github +``` + +但只有: + +```text +secret:openai +``` + +必须: + +```text +ACCESS_DENIED +``` + +--- + +# 117. Conflict Test + +安装: + +```text +Plugin A +resource = foo.bar +``` + +然后: + +```text +Plugin B +resource = foo.bar +``` + +必须: + +```text +RESOURCE_NAMESPACE_CONFLICT +``` + +--- + +# 118. Dependency Test + +```text +Plugin A + ↓ +Plugin B +``` + +安装 A 时: + +```text +B not installed +``` + +应该: + +```text +Install B + ↓ +Install A +``` + +--- + +# 119. Failure Test + +Plugin activation: + +```text +throw Error +``` + +必须: + +```text +Plugin = activation_failed +``` + +同时: + +```text +DevOS = healthy +``` + +--- + +# 120. Final Golden Rules + +```text +1. Plugin 是扩展,不是第二个 DevOS。 + +2. Plugin 必须通过 DevOS Runtime 执行业务。 + +3. Plugin 不创建第二套 Auth。 + +4. Plugin 不创建第二套 Task。 + +5. Plugin 不创建第二套 Queue。 + +6. Plugin 不创建第二套 EventBus。 + +7. Plugin 不绕过 Action Runtime。 + +8. Plugin 不绕过 Permission。 + +9. Plugin 不直接读取 Secret。 + +10. Plugin UI 不直接执行业务逻辑。 + +11. Plugin 的 Resource 必须注册到 Resource Registry。 + +12. Plugin 的 Action 必须注册到 Action Registry。 + +13. Plugin 的 Capability 必须注册到 Capability Registry。 + +14. Plugin 的 Skill 必须注册到 Skill Registry。 + +15. Plugin 的 MCP 必须注册到 MCP Runtime。 + +16. Plugin 的 Event 必须进入 Event Runtime。 + +17. Plugin 的 Task 必须进入 Task Runtime。 + +18. Plugin 的日志必须进入 DevOS Logging Runtime。 + +19. Plugin 的审计必须进入 DevOS Audit Runtime。 + +20. Plugin 必须可以独立启停。 + +21. Plugin 崩溃不能拖垮 DevOS Core。 + +22. Plugin 卸载默认不删除业务数据。 + +23. Plugin 升级必须进行兼容性检查。 + +24. Plugin 必须拥有唯一 Namespace。 + +25. Agent 看到的是 Capability,而不是 Plugin 内部实现。 + +26. MCP 是能力接入方式,不是第二套业务 Runtime。 + +27. SEO / DevOps / CRM 等领域都应该优先实现为 Plugin。 + +28. 真正需要独立 Backend 的项目,应从 DevOS Minimal Core Fork。 +``` + +--- + +# 121. DevOS Plugin 最终模型 + +最终 DevOS 应该达到: + +```text + DevOS + │ + ┌──────────────────┴──────────────────┐ + │ │ + Core Runtime Plugin Runtime + │ │ + │ ┌────────────────┼────────────────┐ + │ │ │ │ + │ SEO Plugin DevOps Plugin CRM Plugin + │ │ │ │ + │ Resource Resource Resource + │ Action Action Action + │ Skill Skill Skill + │ MCP MCP MCP + │ Workflow Workflow Workflow + │ Event Event Event + │ UI UI UI + │ │ │ │ + └────────────────────┴────────────────┴────────────────┘ + │ + Capability Registry + │ + Agent + │ + Goal +``` + +DevOS 的真正扩展方式最终就是: + +```text +Core ++ +Plugin ++ +Capability ++ +Agent +``` + +而不是: + +```text +Core ++ +SEO Backend ++ +SEO Queue ++ +SEO Agent ++ +SEO MCP ++ +SEO EventBus +``` + +**这一点必须作为 Zcode 后续所有领域模块开发的架构约束。** + diff --git a/Docs/DevOS-Platform-v2/12_MIGRATION_VERSIONING_COMPATIBILITY.md b/Docs/DevOS-Platform-v2/12_MIGRATION_VERSIONING_COMPATIBILITY.md new file mode 100644 index 0000000..0d12ff5 --- /dev/null +++ b/Docs/DevOS-Platform-v2/12_MIGRATION_VERSIONING_COMPATIBILITY.md @@ -0,0 +1,3008 @@ + +# 12_MIGRATION_VERSIONING_COMPATIBILITY.md + +````md +# DevOS Migration / Versioning / Compatibility + +> Version: 1.0 +> Status: Implementation Specification +> Target: Zcode +> Previous: 11_PLUGIN_RUNTIME.md +> Next: 13_* + +--- + +# 1. 目标 + +DevOS 必须支持长期演进。 + +系统会不断发生: + +- DevOS Core 升级 +- Plugin 升级 +- Resource Schema 升级 +- Action Schema 升级 +- Event Schema 升级 +- Database Migration +- Configuration Migration +- API Migration +- Capability Migration +- Skill Migration + +因此必须建立统一的 Version / Migration / Compatibility Runtime。 + +核心目标: + +```text +旧版本 + ↓ +Compatibility Check + ↓ +Migration Plan + ↓ +Migration + ↓ +新版本 + ↓ +Health Check +```` + +禁止: + +```text +直接覆盖 +直接 ALTER +直接删除旧字段 +直接升级 Plugin +``` + +导致: + +```text +Plugin 崩溃 +数据丢失 +Event Consumer 崩溃 +旧 API 不兼容 +正在执行的 Task 崩溃 +``` + +--- + +# 2. 核心原则 + +DevOS 的版本系统分为: + +```text +Platform Version +Plugin Version +Database Version +API Version +Resource Version +Action Version +Event Version +Skill Version +MCP Version +Configuration Version +``` + +这些版本不能混为一谈。 + +--- + +# 3. Platform Version + +DevOS Core 使用: + +```text +Semantic Versioning +``` + +格式: + +```text +MAJOR.MINOR.PATCH +``` + +例如: + +```text +1.0.0 +1.1.0 +1.1.1 +2.0.0 +``` + +规则: + +```text +MAJOR = Breaking Change + +MINOR = Backward Compatible Feature + +PATCH = Bug Fix +``` + +--- + +# 4. Plugin Version + +Plugin 同样: + +```text +MAJOR.MINOR.PATCH +``` + +例如: + +```text +devos.seo +1.2.3 +``` + +Plugin Version 与 DevOS Version 独立。 + +--- + +# 5. API Version + +DevOS Runtime API: + +```text +apiVersion = 1 +``` + +例如: + +```text +Plugin API v1 +Plugin API v2 +``` + +Plugin Manifest: + +```json +{ + "apiVersion": "1" +} +``` + +--- + +# 6. Runtime API Compatibility + +Plugin 需要声明: + +```json +{ + "apiVersion": "1", + "devos": { + "minVersion": "1.0.0", + "maxVersion": "<2.0.0" + } +} +``` + +如果当前 DevOS: + +```text +2.0.0 +``` + +则 Plugin: + +```text +apiVersion 1 +maxVersion < 2.0.0 +``` + +必须被标记: + +```text +INCOMPATIBLE +``` + +--- + +# 7. Compatibility Matrix + +实现: + +```ts +interface CompatibilityResult { + compatible: boolean + + level: + | 'compatible' + | 'warning' + | 'migration_required' + | 'incompatible' + + reasons: CompatibilityIssue[] + + migrations?: MigrationReference[] +} +``` + +--- + +# 8. Compatibility Issue + +```ts +interface CompatibilityIssue { + code: string + + type: + | 'api' + | 'dependency' + | 'schema' + | 'resource' + | 'action' + | 'event' + | 'config' + | 'runtime' + + severity: + | 'info' + | 'warning' + | 'error' + + message: string +} +``` + +--- + +# 9. Migration Runtime + +统一接口: + +```ts +interface Migration { + id: string + + version: string + + description?: string + + up(context: MigrationContext): Promise + + down?(context: MigrationContext): Promise +} +``` + +--- + +# 10. Migration Context + +```ts +interface MigrationContext { + pluginId?: string + + fromVersion: string + + toVersion: string + + logger: Logger + + database: MigrationDatabase + + config: MigrationConfig + + metadata: Record +} +``` + +--- + +# 11. Migration 必须可追踪 + +数据库: + +```text +schema_migrations +``` + +至少: + +```ts +interface MigrationRecord { + id: string + + namespace: string + + version: string + + checksum: string + + status: + | 'pending' + | 'running' + | 'completed' + | 'failed' + + startedAt?: Date + + completedAt?: Date + + error?: string +} +``` + +--- + +# 12. Migration Namespace + +Migration 必须属于: + +```text +core +plugin +``` + +例如: + +```text +core:2026_001 +seo:2026_001 +devops:2026_002 +``` + +--- + +# 13. Migration ID + +必须唯一: + +```text +core.20260901.add_task_budget + +seo.20260901.add_keyword_difficulty +``` + +禁止: + +```text +001 +002 +003 +``` + +这种全局容易冲突的 ID。 + +--- + +# 14. Migration 顺序 + +Migration 必须按照: + +```text +namespace ++ +version +``` + +确定顺序。 + +例如: + +```text +seo.001 +seo.002 +seo.003 +``` + +不能: + +```text +seo.003 +seo.001 +seo.002 +``` + +--- + +# 15. Migration 不允许自动修改历史 + +一旦: + +```text +Migration = completed +``` + +禁止修改 Migration 文件内容。 + +如果发现错误: + +必须创建新的 Migration: + +```text +seo.004.fix_previous_migration +``` + +--- + +# 16. Migration Checksum + +系统必须计算: + +```text +checksum(Migration) +``` + +如果: + +```text +Migration Record checksum +!= +Current checksum +``` + +必须报错: + +```text +MIGRATION_CHECKSUM_MISMATCH +``` + +防止已经执行的 Migration 被偷偷修改。 + +--- + +# 17. Database Migration + +数据库 Migration 应该使用: + +```text +Prisma Migration +``` + +或 DevOS Database Migration Adapter。 + +推荐: + +```text +Prisma ++ +DevOS Migration Registry +``` + +DevOS Runtime 不应该重新发明完整 SQL Migration Engine。 + +--- + +# 18. Migration Transaction + +如果数据库支持,Migration 应尽量: + +```text +BEGIN + ↓ +Migration + ↓ +COMMIT +``` + +失败: + +```text +ROLLBACK +``` + +但对于: + +```text +大型数据迁移 +外部 API +文件迁移 +``` + +不能强制全部放入单一 Transaction。 + +--- + +# 19. Large Data Migration + +大型 Migration: + +```text +100万 records +``` + +禁止: + +```ts +await db.updateMany(...) +``` + +一次性完成。 + +应该: + +```text +Batch + ↓ +1000 + ↓ +1000 + ↓ +1000 +``` + +并支持: + +```text +progress +checkpoint +resume +``` + +--- + +# 20. Migration Task + +长时间 Migration 必须进入: + +```text +Task Runtime +``` + +即: + +```text +Migration + ↓ +Task + ↓ +Job + ↓ +Worker + ↓ +Migration Action +``` + +不要阻塞 HTTP Request。 + +--- + +# 21. Core Migration + +DevOS Core 升级: + +```text +Old Core + ↓ +Compatibility Check + ↓ +Backup + ↓ +Migration + ↓ +New Core +``` + +--- + +# 22. Plugin Migration + +Plugin: + +```text +1.0.0 + ↓ +1.1.0 +``` + +如果 Schema 改变: + +```text +Migration Required +``` + +例如: + +```text +seo.website +``` + +新增: + +```text +healthScore +``` + +Migration: + +```text +1.0 → 1.1 +``` + +--- + +# 23. Plugin Upgrade + +完整流程: + +```text +Current Plugin + ↓ +Read New Manifest + ↓ +Validate Manifest + ↓ +Resolve Dependencies + ↓ +Compatibility Check + ↓ +Generate Migration Plan + ↓ +Backup + ↓ +Pause New Work + ↓ +Drain Running Work + ↓ +Migration + ↓ +Install New Version + ↓ +Register + ↓ +Health Check + ↓ +Resume +``` + +--- + +# 24. Upgrade Plan + +必须先生成: + +```ts +interface UpgradePlan { + pluginId: string + + fromVersion: string + + toVersion: string + + compatibility: CompatibilityResult + + migrations: MigrationReference[] + + dependencies: DependencyChange[] + + breakingChanges: string[] + + warnings: string[] + + requiresDowntime: boolean + + estimatedRisk: + | 'low' + | 'medium' + | 'high' +} +``` + +UI 应允许管理员在升级前查看。 + +--- + +# 25. Upgrade Preview + +Plugin Settings: + +```text +Upgrade available + +Current: +1.2.0 + +New: +1.3.0 + +Changes: ++ 3 new Actions ++ 2 new Resources ++ 1 DB migration + +Breaking: +None + +Risk: +Low + +[View Changes] +[Upgrade] +``` + +--- + +# 26. Breaking Change + +如果: + +```text +Resource schema breaking +Action input breaking +Action output breaking +Event payload breaking +Plugin API breaking +``` + +必须: + +```text +MAJOR version +``` + +例如: + +```text +1.x.x + ↓ +2.0.0 +``` + +--- + +# 27. Resource Versioning + +Resource: + +```ts +interface ResourceDefinition { + id: string + + version: number + + schema: unknown + + actions: string[] + + events: string[] +} +``` + +例如: + +```text +devos.seo.website +v1 +``` + +--- + +# 28. Resource Schema Evolution + +允许: + +```text +新增 optional field +``` + +例如: + +```json +{ + "name": "example.com", + "healthScore": 92 +} +``` + +旧 Consumer: + +```text +只读取 name +``` + +仍然正常。 + +--- + +# 29. Resource Breaking Change + +例如: + +```text +name +``` + +改成: + +```text +domain +``` + +这是 Breaking Change。 + +不能直接: + +```text +rename name → domain +``` + +应该: + +```text +v1: +name + +v2: +domain +``` + +并提供 Migration。 + +--- + +# 30. Action Versioning + +Action: + +```text +devos.seo.website.scan +``` + +必须支持: + +```text +version +``` + +例如: + +```text +devos.seo.website.scan@1 +devos.seo.website.scan@2 +``` + +--- + +# 31. Action Input Compatibility + +新增 Optional: + +```text +compatible +``` + +删除 Required: + +```text +compatible +``` + +改变类型: + +```text +breaking +``` + +例如: + +```text +timeout: number +``` + +变成: + +```text +timeout: string +``` + +属于 Breaking。 + +--- + +# 32. Action Output Compatibility + +同样: + +```text +新增 optional field +``` + +通常兼容。 + +改变字段类型: + +```text +breaking +``` + +删除字段: + +```text +breaking +``` + +--- + +# 33. Action Runtime Compatibility + +Action Registry 必须能够: + +```text +resolve(actionId, version) +``` + +例如: + +```ts +resolve( + 'devos.seo.website.scan', + 1 +) +``` + +--- + +# 34. Action Alias + +升级期间: + +```text +scan@1 +scan@2 +``` + +可以: + +```text +scan +``` + +默认指向: + +```text +latest compatible +``` + +但正在执行的 Task 必须锁定版本。 + +--- + +# 35. Task Version Lock + +创建 Task: + +```json +{ + "actionId": "devos.seo.website.scan", + "actionVersion": 1 +} +``` + +这样: + +```text +Plugin 升级 +``` + +不会导致: + +```text +正在运行的 Task +``` + +突然使用新版 Action。 + +--- + +# 36. Job Version Lock + +Job 也应该保存: + +```text +actionVersion +pluginVersion +``` + +例如: + +```text +Job + action = seo.scan + actionVersion = 1 + pluginVersion = 1.2.0 +``` + +--- + +# 37. Execution Version + +Execution 必须记录: + +```text +actionVersion +pluginVersion +runtimeVersion +``` + +这样未来可以准确复盘: + +> 当时到底运行的是什么代码? + +--- + +# 38. Event Versioning + +Event: + +```text +devos.seo.website.scanned +``` + +必须: + +```text +version = 1 +``` + +升级: + +```text +version = 2 +``` + +--- + +# 39. Event Backward Compatibility + +推荐: + +```text +Producer + ↓ +Event v2 +``` + +Consumer 可以: + +```text +v1 +v2 +``` + +短期同时支持。 + +--- + +# 40. Event Migration + +Event 通常不应该修改历史。 + +历史: + +```text +event v1 +``` + +保持不变。 + +如果需要: + +```text +v2 +``` + +新 Consumer 使用 v2。 + +不要: + +```text +UPDATE events +SET payload = ... +``` + +批量改历史 Event。 + +--- + +# 41. Event Adapter + +如果 Plugin 只支持: + +```text +v1 +``` + +但系统产生: + +```text +v2 +``` + +可以使用: + +```text +Event Adapter +``` + +例如: + +```text +v2 + ↓ +Adapter + ↓ +v1 + ↓ +Plugin +``` + +--- + +# 42. Skill Version + +Skill: + +```text +devos.seo.audit +``` + +也必须有: + +```text +version +``` + +例如: + +```text +1.0.0 +1.1.0 +``` + +Skill 变化可能包括: + +```text +instructions +requiredCapabilities +inputSchema +outputSchema +``` + +--- + +# 43. Skill Compatibility + +如果只是: + +```text +instruction improvement +``` + +可以 MINOR/PATCH。 + +如果: + +```text +input schema breaking +``` + +应该: + +```text +MAJOR +``` + +--- + +# 44. MCP Version + +MCP Server / Adapter: + +```text +version +``` + +必须记录。 + +Execution: + +```text +mcpServerVersion +``` + +用于故障追踪。 + +--- + +# 45. Capability Version + +Capability: + +```ts +interface Capability { + id: string + + version: number + + type: CapabilityType +} +``` + +Agent Discovery 时: + +```text +capabilityId +version +``` + +--- + +# 46. Capability Compatibility + +Agent Plan 创建后: + +必须锁定: + +```text +capabilityVersion +actionVersion +``` + +否则: + +```text +Agent Plan +``` + +可能在执行过程中因为 Plugin 升级而产生不同结果。 + +--- + +# 47. Agent Plan Version Lock + +例如: + +```json +{ + "steps": [ + { + "capability": "devos.seo.website.scan", + "capabilityVersion": 1, + "actionVersion": 1 + } + ] +} +``` + +这样 Plan 是可复现的。 + +--- + +# 48. Agent Replan + +如果执行时发现: + +```text +Action v1 unavailable +``` + +Agent 可以: + +```text +Observation + ↓ +Compatibility Failure + ↓ +Replan + ↓ +Action v2 +``` + +但是必须记录: + +```text +originalVersion +newVersion +reason +``` + +--- + +# 49. Configuration Version + +Plugin Settings 也必须版本化: + +```ts +interface ConfigurationVersion { + namespace: string + + version: number + + schema: unknown +} +``` + +例如: + +```text +devos.seo.config +v1 +``` + +--- + +# 50. Configuration Migration + +例如: + +旧: + +```json +{ + "model": "gpt-x" +} +``` + +新: + +```json +{ + "ai": { + "model": "gpt-x" + } +} +``` + +Migration: + +```text +v1 → v2 +``` + +--- + +# 51. Config Migration 必须可重复检测 + +如果: + +```text +configVersion = 2 +``` + +再次启动: + +不能再次执行: + +```text +v1 → v2 +``` + +--- + +# 52. Plugin State Migration + +Plugin 状态: + +```text +installed +enabled +disabled +``` + +升级过程中必须有明确状态: + +```text +upgrading +migration_running +activating +health_check +``` + +--- + +# 53. Upgrade Lock + +同一个 Plugin: + +```text +只能同时进行一次 Upgrade +``` + +必须使用: + +```text +Distributed Lock +``` + +例如: + +```text +lock: +plugin:devos.seo +``` + +防止: + +```text +Admin A upgrade +Admin B upgrade +``` + +同时发生。 + +--- + +# 54. Migration Lock + +同一个 Migration Namespace: + +```text +core +seo +devops +``` + +不能并发执行。 + +--- + +# 55. Upgrade Concurrency + +不同 Plugin 可以: + +```text +Plugin A upgrade +Plugin B upgrade +``` + +并行。 + +但: + +```text +同一个 Plugin +``` + +必须串行。 + +--- + +# 56. Running Task During Upgrade + +Plugin 升级时: + +```text +New Jobs +``` + +默认: + +```text +pause +``` + +Running Jobs: + +```text +drain +``` + +如果无法 drain: + +```text +等待 +``` + +超过: + +```text +grace period +``` + +再按照 Plugin Shutdown Policy: + +```text +cancel +checkpoint +force stop +``` + +--- + +# 57. Task Compatibility + +Task 必须保存: + +```text +pluginVersion +actionVersion +runtimeVersion +``` + +如果升级后仍然可以执行: + +继续。 + +否则: + +```text +blocked +``` + +并产生: + +```text +task.compatibility_failed +``` + +--- + +# 58. Job Compatibility + +Job 创建后: + +```text +job.actionVersion +``` + +固定。 + +Worker 执行: + +```text +Action Registry + ↓ +Resolve exact version +``` + +而不是: + +```text +latest +``` + +--- + +# 59. Execution Reproducibility + +Execution Detail 页面必须显示: + +```text +DevOS: +1.8.2 + +Plugin: +devos.seo 1.4.0 + +Action: +seo.website.scan v2 + +Skill: +seo.audit v1 + +MCP: +browser v3 +``` + +这对于 Debug 非常重要。 + +--- + +# 60. Database Backup + +高风险 Migration 前必须支持: + +```text +Backup +``` + +但不要强制 DevOS 自己实现 PostgreSQL Backup Engine。 + +提供: + +```ts +interface BackupProvider { + createBackup(scope?: BackupScope): Promise +} +``` + +可以接: + +```text +pg_dump +cloud snapshot +managed database backup +``` + +--- + +# 61. Backup Policy + +Migration 可以声明: + +```ts +interface MigrationPolicy { + requiresBackup: boolean + + allowDestructive: boolean + + maxDowntimeSeconds?: number +} +``` + +--- + +# 62. Destructive Migration + +例如: + +```text +DROP COLUMN +DROP TABLE +DELETE DATA +``` + +必须: + +```text +destructive = true +``` + +并需要: + +```text +explicit approval +``` + +--- + +# 63. Production Migration + +生产环境: + +```text +destructive migration +``` + +必须: + +```text +Preview ++ +Backup ++ +Approval +``` + +--- + +# 64. Zero Downtime + +支持: + +```text +Expand + ↓ +Migrate + ↓ +Contract +``` + +例如字段改名: + +错误: + +```text +DROP name +ADD domain +``` + +推荐: + +```text +Phase 1: +ADD domain + +Phase 2: +write both + +Phase 3: +backfill + +Phase 4: +read domain + +Phase 5: +remove name +``` + +--- + +# 65. Expand / Contract + +这是 DevOS 推荐的生产数据库演进方式。 + +```text +Old + ↓ +Expand + ↓ +Dual Read/Write + ↓ +Backfill + ↓ +Switch + ↓ +Contract +``` + +--- + +# 66. Plugin Upgrade Rollout + +未来支持: + +```text +Canary +``` + +例如: + +```text +10% Organization + ↓ +Health + ↓ +50% + ↓ +Health + ↓ +100% +``` + +第一阶段可以不实现 UI,但 Runtime 数据模型预留: + +```text +rolloutStrategy +``` + +--- + +# 67. Plugin Rollback + +Rollback: + +```text +Current 1.3.0 + ↓ +Rollback + ↓ +1.2.0 +``` + +但是必须先检查: + +```text +Database Schema +Data Migration +Action Compatibility +Event Compatibility +Task Compatibility +``` + +--- + +# 68. Rollback 不等于 Git Checkout + +禁止简单: + +```text +npm install plugin@old +``` + +然后认为已经 Rollback。 + +如果: + +```text +DB schema = v3 +``` + +而旧 Plugin 只支持: + +```text +DB schema = v2 +``` + +必须: + +```text +Compatibility Check +``` + +--- + +# 69. Failed Upgrade Recovery + +如果升级失败: + +```text +Upgrade + ↓ +Failure +``` + +必须记录: + +```text +upgrade_failed +``` + +包含: + +```text +fromVersion +toVersion +failedStep +migration +error +timestamp +``` + +--- + +# 70. Recovery State + +Plugin 状态: + +```text +upgrade_failed +``` + +不能继续正常运行。 + +管理员看到: + +```text +Plugin upgrade failed + +Current state: +Recovery required + +[View Error] +[Retry] +[Rollback] +``` + +--- + +# 71. Migration Events + +Migration 必须产生: + +```text +migration.started +migration.completed +migration.failed +migration.rolled_back +``` + +Plugin: + +```text +plugin.upgrade.started +plugin.upgrade.completed +plugin.upgrade.failed +plugin.rollback.completed +``` + +--- + +# 72. Migration Audit + +所有 Migration: + +```text +Audit +``` + +例如: + +```text +Admin Alice + ↓ +core.plugin.upgrade + ↓ +devos.seo +1.2.0 → 1.3.0 + ↓ +SUCCESS +``` + +--- + +# 73. Migration Logs + +必须使用: + +```text +Logger +``` + +自动带: + +```text +migrationId +pluginId +fromVersion +toVersion +``` + +--- + +# 74. Migration Metrics + +至少: + +```text +devos_migration_total + +devos_migration_success_total + +devos_migration_failed_total + +devos_migration_duration_ms +``` + +--- + +# 75. Version Registry + +实现: + +```ts +interface VersionRegistry { + register(component: VersionedComponent): void + + get(id: string): VersionedComponent[] + + resolve( + id: string, + version?: string + ): VersionedComponent | undefined +} +``` + +--- + +# 76. Versioned Component + +```ts +interface VersionedComponent { + id: string + + version: string + + type: + | 'plugin' + | 'resource' + | 'action' + | 'skill' + | 'mcp' + | 'event' + | 'api' +} +``` + +--- + +# 77. Compatibility Registry + +实现: + +```ts +interface CompatibilityRegistry { + check( + from: VersionedComponent, + to: VersionedComponent + ): CompatibilityResult +} +``` + +--- + +# 78. Version Resolver + +解析: + +```text +^1.2.0 +>=1.0.0 <2.0.0 +1.4.2 +``` + +推荐使用成熟 SemVer Library。 + +不要自行实现 SemVer Parser。 + +--- + +# 79. Dependency Resolver + +Plugin Dependency: + +```text +A + ↓ +B ^1.2.0 +``` + +Resolver 必须: + +```text +find compatible version +``` + +如果: + +```text +B installed = 2.0.0 +``` + +则: + +```text +INCOMPATIBLE +``` + +--- + +# 80. Dependency Upgrade + +如果: + +```text +A → B ^1 +C → B ^2 +``` + +不能简单升级 B。 + +必须检测: + +```text +dependency conflict +``` + +第一阶段: + +允许多个版本仅在 Runtime 明确支持的情况下存在。 + +否则: + +```text +reject +``` + +--- + +# 81. Plugin Lock File + +DevOS 项目应该支持: + +```text +devos.lock +``` + +例如: + +```yaml +plugins: + devos.seo: + version: 1.4.0 + checksum: abc123 + + devos.browser: + version: 2.1.0 + checksum: def456 +``` + +用于: + +```text +production +CI/CD +clone +deployment +``` + +保证环境一致。 + +--- + +# 82. Environment Reproducibility + +开发: + +```text +devos.lock +``` + +生产: + +```text +devos.lock +``` + +必须得到相同 Plugin Version。 + +--- + +# 83. Plugin Installation Modes + +支持: + +```text +development +staging +production +``` + +Development: + +```text +local plugin +hot reload +``` + +Production: + +```text +immutable version +checksum +``` + +--- + +# 84. Immutable Production Plugin + +生产环境禁止: + +```text +latest +``` + +必须: + +```text +exact version ++ +checksum +``` + +例如: + +```text +devos.seo@1.4.0 +sha256=... +``` + +--- + +# 85. Core Upgrade + +DevOS Core 升级也必须产生: + +```text +Upgrade Plan +Migration Plan +Compatibility Report +``` + +例如: + +```text +DevOS 1.8.0 → 1.9.0 + +Database: +3 migrations + +API: +compatible + +Plugins: +12 compatible +1 warning +1 incompatible +``` + +--- + +# 86. Preflight Check + +升级前: + +```text +devos upgrade check +``` + +输出: + +```text +Core: +compatible + +Database: +ready + +Plugins: +12 OK +1 warning +1 incompatible + +Running Tasks: +3 + +Backup: +available + +Result: +NOT READY +``` + +--- + +# 87. Upgrade CLI + +至少: + +```text +devos version + +devos upgrade check + +devos upgrade plan + +devos upgrade + +devos migrate status + +devos migrate run +``` + +CLI 必须进入: + +```text +Action Runtime +``` + +如果这些操作属于改变系统状态。 + +--- + +# 88. Upgrade API + +提供: + +```http +GET /api/system/version + +GET /api/system/upgrade/check + +GET /api/system/upgrade/plan + +POST /api/system/upgrade +``` + +--- + +# 89. Migration API + +```http +GET /api/migrations +GET /api/migrations/:id +POST /api/migrations/:id/run +``` + +Production 中: + +```text +run +``` + +必须进行: + +```text +Permission +Approval +``` + +--- + +# 90. UI:System Upgrade + +DevOS Settings: + +```text +System + ├── Version + ├── Updates + ├── Migrations + └── Compatibility +``` + +--- + +# 91. UI:Plugin Upgrade + +Plugin Settings: + +```text +Version 1.2.0 + +Update available: +1.3.0 + +Compatibility: +✓ API +✓ Database +✓ Dependencies +⚠ Running tasks + +Migration: +2 steps + +[View Plan] +[Upgrade] +``` + +--- + +# 92. UI:Migration Detail + +显示: + +```text +Migration + +ID: +seo.20260901.add_health_score + +From: +1.2.0 + +To: +1.3.0 + +Status: +Completed + +Duration: +4.2s + +Records: +12,381 +``` + +--- + +# 93. Migration Dry Run + +支持: + +```text +dryRun = true +``` + +例如: + +```text +devos migrate plan +``` + +输出: + +```text +Will: +ADD column health_score +BACKFILL 12,381 rows + +Will NOT: +DELETE data +``` + +--- + +# 94. Migration Validation + +Migration 前: + +```text +validate() +``` + +Migration 后: + +```text +verify() +``` + +例如: + +```ts +interface Migration { + validate?(): Promise + + up(): Promise + + verify?(): Promise +} +``` + +--- + +# 95. Data Integrity + +Migration 必须能够验证: + +```text +row count +foreign key +unique constraint +required field +data format +``` + +--- + +# 96. Migration Checkpoint + +大型 Migration: + +```ts +interface MigrationCheckpoint { + migrationId: string + + cursor?: string + + processed: number + + total?: number + + updatedAt: Date +} +``` + +Worker Crash: + +```text +Resume +``` + +而不是: + +```text +从 0 开始 +``` + +--- + +# 97. Migration 与 Queue + +大型 Migration 应该: + +```text +Task + ↓ +Job + ↓ +Worker +``` + +例如: + +```text +Migration Task + ├── Batch Job 1 + ├── Batch Job 2 + ├── Batch Job 3 + └── Batch Job N +``` + +--- + +# 98. Migration 与 Event + +Migration 大量修改数据时: + +默认不要产生: + +```text +100000 business events +``` + +例如: + +```text +backfill website.healthScore +``` + +不应该自动发送: + +```text +website.updated +``` + +100000 次。 + +Migration 可以声明: + +```ts +emitEvents: false +``` + +--- + +# 99. Migration Event Policy + +支持: + +```text +none +summary +full +``` + +例如: + +```text +none: +不产生业务 Event + +summary: +产生 migration.completed + +full: +产生每条业务 Event +``` + +默认: + +```text +summary +``` + +--- + +# 100. Final Architecture + +完成本规范后: + +```text + DevOS + │ + Version Registry + │ + ┌──────────────┼──────────────┐ + ↓ ↓ ↓ + Core Plugin API + Version Version Version + │ │ │ + └──────────────┼──────────────┘ + ↓ + Compatibility Runtime + │ + Upgrade Planner + │ + ┌────────┴────────┐ + ↓ ↓ + Migration Dependency + Runtime Resolver + │ + ↓ + Task Runtime + │ + ↓ + Job + │ + ↓ + Worker + │ + ↓ + Database + │ + ↓ + Event + │ + ↓ + Observability +``` + +--- + +# 101. 完整版本链 + +DevOS 最终必须能够回答: + +> 这个结果到底是哪个版本产生的? + +例如: + +```text +User + ↓ +Agent + ↓ +Goal + ↓ +Skill v2 + ↓ +Capability v3 + ↓ +Plugin devos.seo v1.8.2 + ↓ +Action seo.website.scan v2 + ↓ +Task + ↓ +Job + ↓ +Execution + ↓ +MCP browser v4 + ↓ +Event v2 + ↓ +Result +``` + +所有关键节点都可追踪。 + +--- + +# 102. Acceptance Criteria + +## Version + +* [ ] Core Version +* [ ] Plugin Version +* [ ] API Version +* [ ] Resource Version +* [ ] Action Version +* [ ] Skill Version +* [ ] MCP Version +* [ ] Event Version +* [ ] Configuration Version + +## Migration + +* [ ] Migration Registry +* [ ] Migration Record +* [ ] Migration Checksum +* [ ] Migration Ordering +* [ ] Migration Transaction +* [ ] Migration Dry Run +* [ ] Migration Validation +* [ ] Migration Verification +* [ ] Migration Checkpoint +* [ ] Large Data Migration +* [ ] Migration Retry + +## Compatibility + +* [ ] Compatibility Check +* [ ] Dependency Resolver +* [ ] API Compatibility +* [ ] Resource Compatibility +* [ ] Action Compatibility +* [ ] Event Compatibility +* [ ] Plugin Compatibility +* [ ] Configuration Compatibility + +## Upgrade + +* [ ] Upgrade Check +* [ ] Upgrade Plan +* [ ] Upgrade Preview +* [ ] Backup +* [ ] Upgrade Lock +* [ ] Running Task Drain +* [ ] Migration +* [ ] Health Check +* [ ] Rollback Strategy +* [ ] Upgrade Failure Recovery + +## Reproducibility + +* [ ] devos.lock +* [ ] Plugin checksum +* [ ] Exact Action Version +* [ ] Exact Plugin Version +* [ ] Exact MCP Version +* [ ] Execution Version Metadata + +## UI + +* [ ] System Version +* [ ] Upgrade Check +* [ ] Upgrade Plan +* [ ] Migration List +* [ ] Migration Detail +* [ ] Plugin Upgrade +* [ ] Compatibility Report + +--- + +# 103. Integration Tests + +必须测试: + +## Test 1 + +```text +Plugin 1.0 + ↓ +Upgrade + ↓ +Plugin 1.1 + ↓ +Migration + ↓ +Success +``` + +--- + +## Test 2 + +Migration 修改数据库失败: + +```text +Migration + ↓ +Error + ↓ +Rollback +``` + +数据库必须保持一致。 + +--- + +## Test 3 + +Migration Checksum: + +```text +Executed Migration + ↓ +Modify Migration File + ↓ +Startup + ↓ +CHECKSUM_MISMATCH +``` + +--- + +## Test 4 + +Action Version: + +```text +Task created +actionVersion = 1 + +Plugin upgraded + +Task executes + ↓ +Action v1 +``` + +不能自动变成 v2。 + +--- + +## Test 5 + +Agent Plan: + +```text +Plan + ↓ +Capability v1 + ↓ +Plugin upgrade + ↓ +Execution +``` + +必须仍然按照 Plan 锁定的版本执行,或者明确触发 Replan。 + +--- + +## Test 6 + +Event Version: + +```text +Event v1 +Event v2 +``` + +两个 Consumer 可以分别消费。 + +--- + +## Test 7 + +Plugin Dependency: + +```text +A → B ^1 +B = 2 +``` + +必须: + +```text +INCOMPATIBLE +``` + +--- + +## Test 8 + +Production Plugin: + +```text +plugin@latest +``` + +必须拒绝。 + +必须使用: + +```text +exact version ++ +checksum +``` + +--- + +## Test 9 + +Concurrent Upgrade: + +```text +Admin A → upgrade SEO +Admin B → upgrade SEO +``` + +只能允许一个执行。 + +--- + +## Test 10 + +Large Migration: + +```text +1,000,000 records +``` + +Worker Crash: + +```text +50% + ↓ +restart + ↓ +resume +``` + +不能重新处理全部数据。 + +--- + +# 104. Zcode Implementation Rules + +Zcode 实现时必须遵守: + +```text +1. 不自行发明完整 SemVer。 + +2. 不自行发明完整 Database Migration Engine。 + +3. 不修改已经执行的 Migration。 + +4. 不直接修改历史 Event。 + +5. 不让 Task 使用 latest Action。 + +6. 不让 Execution 使用 latest Plugin。 + +7. 不在升级过程中破坏 Running Task。 + +8. 不允许两个相同 Plugin 同时 Upgrade。 + +9. Production 禁止使用 latest Plugin。 + +10. Production Plugin 必须有 checksum。 + +11. Breaking Change 必须明确版本升级。 + +12. 长时间 Migration 必须使用 Task/Job/Worker。 + +13. Migration 必须产生 Audit。 + +14. Migration 必须产生 Observability 数据。 + +15. Upgrade 必须有 Compatibility Check。 + +16. Plugin Upgrade 必须有 Upgrade Plan。 + +17. Destructive Migration 必须显式批准。 + +18. Event Schema 必须版本化。 + +19. Action Schema 必须版本化。 + +20. Agent Plan 必须记录能力版本。 + +21. Execution 必须记录实际运行版本。 + +22. Rollback 必须经过 Compatibility Check。 + +23. Plugin 卸载不能默认删除业务数据。 + +24. Core Runtime 必须能够在 Plugin 升级失败时继续运行。 +``` + +--- + +# 105. 最终 Golden Rule + +DevOS 必须做到: + +```text +Never ask: + +"现在安装的是什么版本?" + +而应该能够回答: + +"这个 Execution 当时运行的准确版本是什么?" +``` + +因此最终 Execution 必须至少保存: + +```text +runtimeVersion +pluginVersion +actionVersion +skillVersion +mcpVersion +eventVersion +``` + +形成: + +```text + Execution + │ + ┌─────────────┼─────────────┐ + ↓ ↓ ↓ + Runtime Plugin Action + Version Version Version + │ │ │ + └─────────────┼─────────────┘ + ↓ + Skill Version + ↓ + MCP Version + ↓ + Event Version +``` + +**这套 Version Lock 是 DevOS 能够真正作为长期运行的 Developer Work OS,而不是“一次性后台项目”的关键基础设施。** + + diff --git a/Docs/DevOS-Platform-v2/13_DEPLOYMENT_ENVIRONMENT_CONFIG_RUNTIME.md b/Docs/DevOS-Platform-v2/13_DEPLOYMENT_ENVIRONMENT_CONFIG_RUNTIME.md new file mode 100644 index 0000000..6c2adc9 --- /dev/null +++ b/Docs/DevOS-Platform-v2/13_DEPLOYMENT_ENVIRONMENT_CONFIG_RUNTIME.md @@ -0,0 +1,4971 @@ + +# DevOS Deployment / Environment / Configuration Runtime + +> Document: 13 +> Status: Required +> Audience: Zcode / DevOS Core Team +> Purpose: 定义 DevOS 的部署、环境、配置、Secrets、Runtime Profile 与基础设施运行模型 +> Depends On: +> - 03_RESOURCE_ACTION_MODEL.md +> - 06_MCP_SKILL_AGENT_RUNTIME.md +> - 09_TASK_JOB_QUEUE_RUNTIME.md +> - 12_MIGRATION_VERSIONING_COMPATIBILITY.md + +--- + +# 1. Goals + +DevOS 不能只定义业务 Runtime。 + +它必须能够回答: + +- DevOS 当前运行在哪个环境? +- 当前是什么版本? +- 当前连接哪个数据库? +- Redis 在哪里? +- 当前启用了哪些 Plugin? +- 当前 Worker 有多少? +- 当前 Agent 使用什么 Model? +- 哪些配置属于公开配置? +- 哪些配置属于 Secret? +- Plugin 的配置如何保存? +- 不同环境如何隔离? +- Docker / Kubernetes / VM / Bare Metal 如何部署? +- 如何启动 API? +- 如何启动 Worker? +- 如何执行 Migration? +- 如何进行健康检查? +- 如何优雅关闭? +- 如何进行升级? +- 如何进行回滚? +- 如何发现配置错误? + +因此 DevOS 必须增加: + +```text +Deployment Runtime +Environment Runtime +Configuration Runtime +Secret Runtime +Runtime Profile +Health Runtime +Bootstrap Runtime +Shutdown Runtime +```` + +--- + +# 2. Architecture + +整体架构: + +```text + DevOS + │ + ┌─────────────┴─────────────┐ + │ │ + Application Runtime Infrastructure Runtime + │ │ + ┌─────┼─────┐ ┌───────┼────────┐ + │ │ │ │ │ │ + API Worker Agent Config Secret Health + │ │ │ │ │ │ + └─────┴─────┘ └───────┼────────┘ + │ + Environment Runtime + │ + ┌───────────────┼───────────────┐ + │ │ │ + Local Staging Production + │ │ │ + PostgreSQL PostgreSQL PostgreSQL + Redis Redis Redis + Storage Storage Storage +``` + +DevOS Runtime 不应该直接读取: + +```text +process.env.XYZ +``` + +业务代码也不应该直接: + +```text +process.env.OPENAI_API_KEY +process.env.DATABASE_URL +process.env.REDIS_URL +``` + +所有配置必须经过: + +```text +Configuration Runtime +``` + +统一解析。 + +--- + +# 3. Core Concepts + +DevOS 定义以下概念: + +```text +Environment +Runtime Profile +Configuration +Secret +Configuration Source +Configuration Schema +Configuration Snapshot +Deployment +Instance +Service +Health Check +``` + +关系: + +```text +Environment + │ + ├── Configuration + ├── Secrets + ├── Runtime Profile + ├── Deployments + │ + └── Instances + │ + ├── API + ├── Worker + ├── Scheduler + └── Agent +``` + +--- + +# 4. Environment + +Environment 表示一个完整运行环境。 + +例如: + +```text +local +development +test +staging +production +``` + +推荐默认: + +```text +local +development +staging +production +``` + +Environment 是 Resource: + +```text +core.environment +``` + +--- + +# 5. Environment Interface + +```ts +export interface Environment { + id: string + + organizationId?: string + + key: string + + name: string + + description?: string + + type: + | 'local' + | 'development' + | 'test' + | 'staging' + | 'production' + | 'custom' + + status: + | 'active' + | 'inactive' + | 'maintenance' + + isProduction: boolean + + configVersion: number + + runtimeVersion: string + + metadata?: Record + + createdAt: Date + updatedAt: Date +} +``` + +--- + +# 6. Environment Isolation + +不同 Environment 必须严格隔离。 + +至少隔离: + +```text +Database +Redis +Object Storage +Secrets +Queues +Task +Job +Execution +Logs +Artifacts +Plugin Configuration +Agent Memory +External Credentials +``` + +禁止: + +```text +production Task + ↓ +staging Queue +``` + +禁止: + +```text +production Secret + ↓ +development Runtime +``` + +除非显式配置并通过 Policy。 + +--- + +# 7. Runtime Profile + +Runtime Profile 描述某个 DevOS 实例应该运行什么。 + +例如: + +```text +api +worker +scheduler +agent +all-in-one +``` + +定义: + +```ts +export interface RuntimeProfile { + id: string + + key: string + + name: string + + services: RuntimeService[] + + environment: string + + configOverrides?: Record + + metadata?: Record +} +``` + +--- + +# 8. Runtime Service + +```ts +export type RuntimeServiceType = + | 'api' + | 'worker' + | 'scheduler' + | 'agent' + | 'event-consumer' + | 'mcp' + | 'plugin-host' + | 'migration' +``` + +```ts +export interface RuntimeService { + id: string + + type: RuntimeServiceType + + enabled: boolean + + replicas?: number + + concurrency?: number + + queues?: string[] + + capabilities?: string[] + + resources?: { + cpu?: string + memory?: string + } + + metadata?: Record +} +``` + +--- + +# 9. Default Runtime Profiles + +DevOS 必须提供: + +## 9.1 all-in-one + +适合: + +```text +个人开发 +小型部署 +Demo +单机服务器 +``` + +运行: + +```text +API +Worker +Scheduler +Agent +MCP +``` + +--- + +## 9.2 api + +只运行: + +```text +API +``` + +--- + +## 9.3 worker + +运行: + +```text +Worker +Task +Job +Queue +``` + +--- + +## 9.4 scheduler + +运行: + +```text +Scheduler +Event Trigger +Webhook Trigger +``` + +--- + +## 9.5 agent + +运行: + +```text +Agent Runtime +Agent Scheduler +Agent Execution +``` + +--- + +# 10. Configuration Runtime + +配置必须统一进入: + +```text +ConfigurationRuntime +``` + +接口: + +```ts +export interface ConfigurationRuntime { + get( + key: string, + options?: ConfigurationGetOptions + ): T + + getOrThrow( + key: string, + options?: ConfigurationGetOptions + ): T + + has(key: string): boolean + + resolve(): Promise + + validate(): Promise + + reload(): Promise + + version(): number +} +``` + +--- + +# 11. Configuration Sources + +支持: + +```text +1. Built-in Defaults +2. Configuration File +3. Environment Variables +4. Database +5. Secret Manager +6. Plugin Configuration +7. Environment Configuration +8. Runtime Overrides +``` + +优先级: + +```text +Runtime Override + ↓ +Secret Manager + ↓ +Environment Configuration + ↓ +Plugin Configuration + ↓ +Environment Variables + ↓ +Configuration File + ↓ +Built-in Default +``` + +但 Secret 不应该简单等价于普通 Configuration。 + +--- + +# 12. Configuration Schema + +每个配置必须声明 Schema。 + +例如: + +```ts +export interface ConfigurationDefinition { + key: string + + description?: string + + schema: unknown + + defaultValue?: T + + required?: boolean + + secret?: boolean + + readonly?: boolean + + reloadable?: boolean + + sensitive?: boolean + + scope: + | 'system' + | 'environment' + | 'organization' + | 'project' + | 'plugin' + | 'user' + + validator?: ( + value: T + ) => Promise | void +} +``` + +推荐: + +```text +Zod +``` + +例如: + +```ts +const config = defineConfig({ + key: 'redis.url', + + schema: z.string().url(), + + required: true, + + secret: true, + + scope: 'environment' +}) +``` + +--- + +# 13. Configuration Namespace + +配置必须使用 Namespace。 + +例如: + +```text +core.database.url +core.redis.url + +core.http.port +core.http.host + +core.storage.provider +core.storage.bucket + +core.agent.defaultModel + +core.agent.maxIterations + +core.queue.defaultConcurrency + +core.scheduler.enabled +``` + +Plugin: + +```text +plugin.github.token +plugin.github.apiUrl + +plugin.openai.apiKey +plugin.openai.defaultModel + +plugin.seo.defaultTimeout +``` + +禁止 Plugin 使用: + +```text +DATABASE_URL +REDIS_URL +OPENAI_KEY +``` + +作为业务代码内部 API。 + +--- + +# 14. Environment Variables + +Environment Variables 可以作为 Configuration Source。 + +例如: + +```text +DEVOS_CORE_HTTP_PORT=3000 + +DEVOS_CORE_DATABASE_URL=... + +DEVOS_CORE_REDIS_URL=... + +DEVOS_PLUGIN_OPENAI_API_KEY=... +``` + +映射: + +```text +DEVOS_CORE_HTTP_PORT + ↓ +core.http.port +``` + +规则: + +```text +DEVOS_ +namespace +key +``` + +推荐转换: + +```text +. +→ +_ +``` + +例如: + +```text +core.database.url +``` + +变成: + +```text +DEVOS_CORE_DATABASE_URL +``` + +--- + +# 15. Secret Runtime + +Secret 必须独立于普通 Configuration。 + +定义: + +```ts +export interface SecretReference { + id: string + + key: string + + provider: + | 'database' + | 'env' + | 'vault' + | 'external' + | 'custom' + + version?: string + + metadata?: Record +} +``` + +代码中: + +```ts +const token = await secrets.get( + 'plugin.github.token' +) +``` + +禁止: + +```ts +console.log(token) +``` + +--- + +# 16. Secret Storage + +DevOS 最少支持: + +```text +env +database-encrypted +external +``` + +未来支持: + +```text +HashiCorp Vault +AWS Secrets Manager +GCP Secret Manager +Azure Key Vault +Kubernetes Secrets +``` + +但是: + +```text +SecretProvider +``` + +必须抽象。 + +```ts +export interface SecretProvider { + get( + key: string, + context: SecretContext + ): Promise + + set( + key: string, + value: string, + context: SecretContext + ): Promise + + delete( + key: string, + context: SecretContext + ): Promise + + exists( + key: string, + context: SecretContext + ): Promise +} +``` + +--- + +# 17. Secret Encryption + +如果使用 Database 保存 Secret: + +必须: + +```text +Encryption at Rest +``` + +禁止明文保存: + +```text +apiKey +password +accessToken +refreshToken +privateKey +webhookSecret +cookie +sessionSecret +``` + +数据库保存: + +```text +ciphertext +keyVersion +algorithm +createdAt +updatedAt +``` + +--- + +# 18. Secret Redaction + +日志系统必须自动隐藏: + +```text +API Key +Token +Password +Cookie +Authorization +Private Key +Secret +``` + +例如: + +```text +Authorization: Bearer sk-xxxx +``` + +必须变成: + +```text +Authorization: Bearer [REDACTED] +``` + +--- + +# 19. Configuration Snapshot + +每次 Runtime 启动都生成: + +```ts +export interface ConfigurationSnapshot { + id: string + + environmentId: string + + version: number + + values: Record + + secretKeys: string[] + + checksum: string + + createdAt: Date +} +``` + +注意: + +```text +Snapshot 中不能保存 Secret 明文。 +``` + +只保存: + +```text +secretKeys +secret references +``` + +--- + +# 20. Runtime Reproducibility + +每一个: + +```text +Task +Job +Execution +AgentRun +``` + +都应该记录: + +```text +environmentId +configVersion +runtimeVersion +plugin versions +``` + +这样可以回答: + +> 为什么这个任务昨天成功,今天失败? + +可以定位: + +```text +Runtime Version ++ +Configuration Version ++ +Plugin Version ++ +Action Version ++ +Model Version +``` + +--- + +# 21. Configuration Versioning + +配置必须有版本。 + +```ts +export interface ConfigurationVersion { + version: number + + environmentId: string + + checksum: string + + createdBy: string + + createdAt: Date + + changes: ConfigurationChange[] +} +``` + +```ts +export interface ConfigurationChange { + key: string + + oldValue?: unknown + + newValue?: unknown + + changedBy: string + + reason?: string +} +``` + +Secret 的值不能出现在: + +```text +oldValue +newValue +logs +audit message +``` + +只能: + +```text +changed: true +``` + +--- + +# 22. Configuration Change Flow + +配置修改: + +```text +User + ↓ +Configuration UI + ↓ +Configuration Action + ↓ +Authorization + ↓ +Validation + ↓ +Configuration Runtime + ↓ +New Configuration Version + ↓ +Audit Event + ↓ +Reload / Restart +``` + +不能: + +```text +UI + ↓ +直接修改 DB +``` + +--- + +# 23. Configuration Actions + +Configuration 是 Resource。 + +```text +core.configuration +``` + +Actions: + +```text +core.configuration.get + +core.configuration.list + +core.configuration.set + +core.configuration.update + +core.configuration.validate + +core.configuration.reload + +core.configuration.rollback + +core.configuration.diff +``` + +Secret: + +```text +core.secret.list + +core.secret.getMetadata + +core.secret.set + +core.secret.rotate + +core.secret.delete +``` + +注意: + +```text +core.secret.get +``` + +默认禁止。 + +UI 也不应该直接展示 Secret 原文。 + +--- + +# 24. Plugin Configuration + +Plugin Manifest 可以声明: + +```ts +export interface PluginConfigDefinition { + key: string + + schema: unknown + + defaultValue?: unknown + + required?: boolean + + secret?: boolean + + reloadable?: boolean +} +``` + +例如: + +```ts +const plugin: PluginManifest = { + id: 'github', + + config: [ + { + key: 'apiUrl', + schema: z.string().url(), + defaultValue: 'https://api.github.com' + }, + { + key: 'token', + schema: z.string(), + required: true, + secret: true + } + ] +} +``` + +安装 Plugin 后: + +```text +Plugin + ↓ +Manifest + ↓ +Configuration Registry + ↓ +Configuration UI +``` + +自动出现: + +```text +Settings + └── Plugins + └── GitHub + ├── General + ├── Credentials + └── Advanced +``` + +--- + +# 25. Dynamic Configuration UI + +Configuration Schema 应该能够驱动 UI。 + +例如: + +```ts +{ + key: 'core.agent.maxIterations', + type: 'number', + min: 1, + max: 100 +} +``` + +UI 自动生成: + +```text +Max Iterations +[ 20 ] +``` + +Secret: + +```text +OpenAI API Key +[ ************** ] +``` + +Boolean: + +```text +Enable Scheduler +[ ON ] +``` + +Enum: + +```text +Default Model +[ GPT ... ▼ ] +``` + +--- + +# 26. Configuration Field Metadata + +支持: + +```ts +interface ConfigurationUI { + label?: string + + description?: string + + group?: string + + order?: number + + component?: + | 'text' + | 'password' + | 'number' + | 'boolean' + | 'select' + | 'textarea' + | 'json' + | 'code' + + hidden?: boolean + + advanced?: boolean +} +``` + +--- + +# 27. Health Runtime + +DevOS 必须提供统一 Health Runtime。 + +```ts +export interface HealthCheck { + id: string + + name: string + + type: + | 'liveness' + | 'readiness' + | 'startup' + | 'dependency' + + check( + context: HealthContext + ): Promise +} +``` + +--- + +# 28. Health Result + +```ts +export interface HealthResult { + status: + | 'healthy' + | 'degraded' + | 'unhealthy' + + latencyMs?: number + + message?: string + + details?: Record +} +``` + +--- + +# 29. Health Checks + +至少检查: + +```text +Application +Database +Redis +Queue +Storage +Plugin Runtime +MCP Runtime +Agent Runtime +Worker +Scheduler +Configuration +Migration +``` + +例如: + +```text +GET /health +``` + +返回: + +```json +{ + "status": "healthy" +} +``` + +--- + +# 30. Liveness + +Liveness 只回答: + +> 进程是否还活着? + +不能依赖: + +```text +Database +Redis +External API +``` + +例如: + +```text +GET /health/live +``` + +--- + +# 31. Readiness + +Readiness 回答: + +> 当前实例是否可以接受请求? + +检查: + +```text +Database +Redis +Configuration +Migration +Required Plugins +``` + +例如: + +```text +GET /health/ready +``` + +--- + +# 32. Startup + +Startup 检查: + +```text +Configuration loaded +Database connected +Migration completed +Required services initialized +Plugin registry initialized +``` + +--- + +# 33. Dependency Health + +每一个 Plugin 可以注册: + +```ts +plugin.health.register(...) +``` + +例如: + +```text +GitHub + API: healthy + +OpenAI + API: healthy + +Cloudflare + API: degraded +``` + +但是: + +```text +Plugin API unhealthy +``` + +不应该直接导致: + +```text +DevOS Core unhealthy +``` + +除非 Plugin 被标记: + +```text +required: true +``` + +--- + +# 34. Bootstrap Runtime + +DevOS 启动必须经过统一 Bootstrap。 + +```text +Process Start + ↓ +Load Environment + ↓ +Load Configuration + ↓ +Validate Configuration + ↓ +Initialize Logger + ↓ +Initialize Database + ↓ +Check Migration + ↓ +Initialize Redis + ↓ +Initialize Event Bus + ↓ +Initialize Resource Registry + ↓ +Initialize Action Registry + ↓ +Initialize Plugin Runtime + ↓ +Initialize MCP Runtime + ↓ +Initialize Skill Registry + ↓ +Initialize Agent Runtime + ↓ +Initialize Task Runtime + ↓ +Initialize Scheduler + ↓ +Register Health Checks + ↓ +Ready +``` + +--- + +# 35. Bootstrap Phase + +定义: + +```ts +export type BootstrapPhase = + | 'config' + | 'logging' + | 'database' + | 'migration' + | 'redis' + | 'events' + | 'resources' + | 'actions' + | 'plugins' + | 'mcp' + | 'skills' + | 'agents' + | 'tasks' + | 'scheduler' + | 'health' + | 'ready' +``` + +--- + +# 36. Bootstrap Module + +```ts +export interface BootstrapModule { + id: string + + phase: BootstrapPhase + + priority?: number + + dependsOn?: string[] + + initialize( + context: BootstrapContext + ): Promise + + shutdown?( + context: ShutdownContext + ): Promise +} +``` + +--- + +# 37. Plugin Bootstrap + +Plugin 必须支持: + +```ts +export interface PluginRuntime { + initialize(): Promise + + activate(): Promise + + deactivate(): Promise + + health(): Promise +} +``` + +生命周期: + +```text +installed + ↓ +configured + ↓ +initializing + ↓ +active + ↓ +deactivating + ↓ +inactive +``` + +异常: + +```text +failed +``` + +--- + +# 38. Graceful Shutdown + +DevOS 不能直接: + +```text +process.exit() +``` + +正常关闭: + +```text +SIGTERM + ↓ +Mark Instance Draining + ↓ +Stop Accepting New Requests + ↓ +Stop Scheduler + ↓ +Stop Creating New Jobs + ↓ +Worker Drain + ↓ +Wait Running Jobs + ↓ +Close MCP Connections + ↓ +Close Plugin Runtime + ↓ +Close Redis + ↓ +Close Database + ↓ +Flush Logs + ↓ +Exit +``` + +--- + +# 39. Worker Drain + +Worker 收到 shutdown: + +```text +busy jobs +``` + +继续执行。 + +新 Job: + +```text +不再领取 +``` + +最终: + +```text +busy = 0 +``` + +才退出。 + +如果超过: + +```text +shutdownTimeout +``` + +进入: + +```text +forced shutdown +``` + +--- + +# 40. Runtime Instance + +DevOS 运行实例: + +```ts +export interface RuntimeInstance { + id: string + + environmentId: string + + serviceType: RuntimeServiceType + + hostname?: string + + version: string + + status: + | 'starting' + | 'ready' + | 'draining' + | 'stopped' + | 'unhealthy' + + startedAt: Date + + lastHeartbeatAt?: Date + + metadata?: Record +} +``` + +--- + +# 41. Instance Heartbeat + +API / Worker / Scheduler 都必须发送: + +```text +heartbeat +``` + +例如: + +```text +runtime.instance.heartbeat +``` + +用于: + +```text +Instance Discovery +Worker Discovery +Health +Monitoring +Auto Recovery +``` + +--- + +# 42. Deployment + +Deployment 表示一次部署行为。 + +```ts +export interface Deployment { + id: string + + environmentId: string + + version: string + + status: + | 'pending' + | 'deploying' + | 'healthy' + | 'failed' + | 'rolled_back' + + configVersion: number + + startedAt?: Date + + completedAt?: Date + + error?: unknown + + metadata?: Record +} +``` + +Deployment 是 Resource: + +```text +core.deployment +``` + +--- + +# 43. Deployment Actions + +```text +core.deployment.create + +core.deployment.start + +core.deployment.stop + +core.deployment.restart + +core.deployment.rollback + +core.deployment.health + +core.deployment.scale +``` + +--- + +# 44. Deployment Must Use Task Runtime + +部署不是: + +```text +Controller + ↓ +shell exec +``` + +必须: + +```text +Deployment Action + ↓ +Task + ↓ +Jobs + ↓ +Worker + ↓ +Deployment Actions +``` + +例如: + +```text +deploy + ├── validate config + ├── database migration + ├── deploy api + ├── deploy worker + ├── health check + └── finalize +``` + +--- + +# 45. Deployment State Machine + +```text +pending + ↓ +validating + ↓ +deploying + ↓ +migrating + ↓ +starting + ↓ +health_check + ↓ +healthy +``` + +失败: + +```text +deploying + ↓ +failed + ↓ +rollback + ↓ +rolled_back +``` + +--- + +# 46. Docker Support + +DevOS 必须提供官方 Docker 部署方式。 + +至少: + +```text +devos-api +devos-worker +devos-scheduler +devos-agent +``` + +以及: + +```text +postgres +redis +``` + +开发环境可以: + +```text +docker compose up +``` + +--- + +# 47. Docker Compose + +推荐结构: + +```text +deploy/ +└── docker/ + ├── docker-compose.yml + ├── docker-compose.dev.yml + ├── docker-compose.prod.yml + ├── .env.example + └── README.md +``` + +--- + +# 48. Production Architecture + +生产环境推荐: + +```text + Load Balancer + │ + ┌────────┴────────┐ + │ │ + API 1 API 2 + │ │ + └────────┬────────┘ + │ + PostgreSQL + │ + Redis + │ + ┌────────────┼────────────┐ + │ │ │ + Worker 1 Worker 2 Worker N + │ │ │ + └────────────┼────────────┘ + │ + Scheduler + │ + Agent +``` + +--- + +# 49. Kubernetes + +Kubernetes 不是 DevOS Core 的必选依赖。 + +必须提供: + +```text +Deployment +Service +ConfigMap +Secret +Job +CronJob +``` + +对应模板。 + +目录: + +```text +deploy/ +└── kubernetes/ + ├── namespace.yaml + ├── api.yaml + ├── worker.yaml + ├── scheduler.yaml + ├── agent.yaml + ├── configmap.yaml + ├── secret.example.yaml + └── kustomization.yaml +``` + +--- + +# 50. Kubernetes Runtime + +Worker: + +```text +Deployment +``` + +Scheduler: + +```text +Deployment +replicas = 1 +``` + +Migration: + +```text +Job +``` + +不要让: + +```text +每个 API Pod +``` + +同时执行 Migration。 + +--- + +# 51. Migration Lock + +结合: + +```text +12_MIGRATION_VERSIONING_COMPATIBILITY.md +``` + +Migration 必须有: + +```text +distributed lock +``` + +确保: + +```text +API 1 +API 2 +Worker 1 +Worker 2 +``` + +不会同时执行 migration。 + +--- + +# 52. Storage Runtime + +DevOS 需要统一 Storage API。 + +```ts +export interface StorageProvider { + put( + key: string, + data: Buffer | Uint8Array | NodeJS.ReadableStream, + options?: StoragePutOptions + ): Promise + + get( + key: string + ): Promise + + delete( + key: string + ): Promise + + exists( + key: string + ): Promise + + getSignedUrl?( + key: string, + options?: SignedUrlOptions + ): Promise +} +``` + +支持: + +```text +local filesystem +S3 +MinIO +Cloudflare R2 +``` + +--- + +# 53. Artifact Runtime + +Task / Job / Agent / Plugin 产生的文件不能直接散落: + +```text +/tmp +``` + +必须进入: + +```text +Artifact Runtime +``` + +例如: + +```text +core.artifact +``` + +```ts +export interface Artifact { + id: string + + taskId?: string + + jobId?: string + + executionId?: string + + name: string + + mimeType: string + + size: number + + storageKey: string + + checksum?: string + + createdAt: Date +} +``` + +--- + +# 54. Temporary Files + +允许: + +```text +/tmp/devos/* +``` + +但: + +```text +临时文件 ≠ Artifact +``` + +Task 完成后: + +```text +cleanup +``` + +Artifact 必须持久化。 + +--- + +# 55. Runtime Paths + +统一: + +```text +DEVOS_DATA_DIR +DEVOS_CACHE_DIR +DEVOS_TEMP_DIR +DEVOS_LOG_DIR +DEVOS_ARTIFACT_DIR +``` + +例如: + +```text +/data/devos +/data/devos/cache +/data/devos/tmp +/data/devos/logs +/data/devos/artifacts +``` + +业务代码禁止自行: + +```ts +'/tmp/foo' +``` + +必须: + +```ts +runtime.paths.temp(...) +``` + +--- + +# 56. Runtime Paths API + +```ts +export interface RuntimePaths { + data(): string + + cache(): string + + temp(): string + + logs(): string + + artifacts(): string + + plugin(id: string): string +} +``` + +--- + +# 57. External Service Runtime + +所有外部服务必须通过 Provider。 + +例如: + +```text +EmailProvider +StorageProvider +ModelProvider +BrowserProvider +DNSProvider +CloudProvider +GitProvider +SearchProvider +``` + +不要: + +```text +Action + ↓ +直接 fetch("https://api.xxx.com") +``` + +应该: + +```text +Action + ↓ +Provider + ↓ +External API +``` + +--- + +# 58. Provider Registry + +```ts +export interface ProviderRegistry { + register( + type: string, + id: string, + provider: T + ): void + + get( + type: string, + id?: string + ): T + + list( + type: string + ): ProviderInfo[] +} +``` + +例如: + +```text +model.openai +model.anthropic + +storage.s3 +storage.minio + +email.smtp + +git.github +git.gitlab +``` + +--- + +# 59. External Credentials + +Provider Credentials 必须进入: + +```text +Secret Runtime +``` + +例如: + +```text +provider.github.token +provider.cloudflare.apiToken +provider.openai.apiKey +``` + +而不是: + +```text +plugin.github.githubToken +``` + +如果 Credential 属于 Plugin,则 Plugin 可以拥有: + +```text +plugin.github.credentials +``` + +但底层仍然使用: + +```text +Secret Runtime +``` + +--- + +# 60. Runtime Capability Discovery + +Runtime 必须能够告诉 Agent: + +```text +当前环境有哪些能力? +``` + +例如: + +```text +PostgreSQL available +Redis available +GitHub available +OpenAI available +Browser available +Storage available +``` + +但: + +```text +secret value +``` + +绝对不能进入 Capability Discovery。 + +--- + +# 61. Configuration Policy + +配置必须支持 Policy。 + +例如: + +```ts +export interface ConfigurationPolicy { + key: string + + writableBy: + | 'system' + | 'admin' + | 'owner' + + productionEditable: boolean + + requiresApproval?: boolean + + immutable?: boolean +} +``` + +例如: + +```text +production.database.url +``` + +可以: + +```text +immutable = true +``` + +或者: + +```text +requiresApproval = true +``` + +--- + +# 62. Production Safety + +Production 环境默认: + +```text +dangerous configuration +``` + +必须更加严格。 + +例如: + +```text +Database URL +Storage Bucket +Queue Prefix +Encryption Key +Authentication Secret +``` + +不能普通管理员随意修改。 + +--- + +# 63. Configuration Rollback + +配置必须支持: + +```text +Version 1 +Version 2 +Version 3 +``` + +可以: + +```text +rollback Version 2 +``` + +流程: + +```text +User + ↓ +configuration.rollback + ↓ +Authorization + ↓ +Compatibility Check + ↓ +Diff + ↓ +Approval + ↓ +Create Version 4 + ↓ +Apply + ↓ +Health Check +``` + +注意: + +```text +Rollback 不删除 Version 3。 +``` + +而是创建: + +```text +Version 4 +``` + +内容等于: + +```text +Version 2 +``` + +这样审计历史完整。 + +--- + +# 64. Dynamic Reload + +配置定义: + +```text +reloadable: true +``` + +才允许热更新。 + +例如: + +```text +log.level +agent.defaultModel +worker.concurrency +``` + +不适合热更新: + +```text +database.url +encryption.masterKey +runtime.port +``` + +修改这些配置: + +```text +restart required +``` + +--- + +# 65. Reload Flow + +```text +Configuration Update + ↓ +Validate + ↓ +Create Version + ↓ +Apply + ↓ +Notify Config Event + ↓ +Runtime Modules + ↓ +reload() +``` + +Event: + +```text +core.configuration.changed +``` + +--- + +# 66. Configuration Event + +```ts +interface ConfigurationChangedEvent { + environmentId: string + + version: number + + changedKeys: string[] + + reloadableKeys: string[] + + restartRequiredKeys: string[] + + actorId: string + + timestamp: Date +} +``` + +禁止事件包含: + +```text +secret value +``` + +--- + +# 67. Configuration Cache + +Configuration Runtime 可以缓存: + +```text +Resolved Configuration +``` + +但是 Secret: + +```text +短生命周期缓存 +``` + +并且: + +```text +never log +never serialize to event +``` + +--- + +# 68. Environment Context + +所有 ActionContext 必须能够获取: + +```ts +interface EnvironmentContext { + environmentId: string + + environmentType: string + + isProduction: boolean + + configVersion: number + + runtimeVersion: string +} +``` + +Action: + +```ts +ctx.environment +``` + +--- + +# 69. Production Action Policy + +结合: + +```text +03_RESOURCE_ACTION_MODEL.md +``` + +Action 可以声明: + +```ts +interface ActionDefinition { + // existing fields... + + environments?: { + allow?: string[] + + deny?: string[] + } + + production?: { + allowed: boolean + + requiresApproval?: boolean + } +} +``` + +例如: + +```text +server.delete +``` + +默认: + +```text +production.allowed = false +``` + +--- + +# 70. Deployment + Agent + +Agent 可以提出: + +```text +部署新版本 +``` + +但不能绕过: + +```text +Deployment Action +Approval +Policy +Task Runtime +``` + +流程: + +```text +Agent Goal + ↓ +Skill + ↓ +Deployment Capability + ↓ +Plan + ↓ +Approval + ↓ +Task + ↓ +Jobs + ↓ +Deployment Action + ↓ +Health Check +``` + +--- + +# 71. Agent Production Guard + +Agent 在 production 执行: + +```text +deployment +database migration +server delete +DNS change +credential rotation +``` + +必须根据 Policy: + +```text +allow +deny +approval_required +``` + +Agent 不能自行改变 Policy。 + +--- + +# 72. CLI + +增加: + +```bash +devos env list +devos env get production + +devos config list +devos config get core.agent.defaultModel +devos config set core.agent.defaultModel xxx + +devos config validate +devos config diff +devos config rollback + +devos secret list +devos secret set +devos secret rotate + +devos health +devos health live +devos health ready + +devos runtime status +devos runtime instances + +devos deployment list +devos deployment deploy +devos deployment rollback +``` + +Secret CLI 默认: + +```text +不打印 Secret value +``` + +--- + +# 73. API + +Environment: + +```text +GET /api/environments +GET /api/environments/:id +POST /api/environments +PATCH /api/environments/:id +DELETE /api/environments/:id +``` + +Configuration: + +```text +GET /api/config +GET /api/config/:key +PATCH /api/config/:key + +POST /api/config/validate +POST /api/config/reload + +GET /api/config/versions +GET /api/config/diff +POST /api/config/rollback +``` + +Health: + +```text +GET /health +GET /health/live +GET /health/ready +GET /health/startup +``` + +Runtime: + +```text +GET /api/runtime +GET /api/runtime/instances +GET /api/runtime/instances/:id +``` + +Deployment: + +```text +GET /api/deployments +POST /api/deployments +GET /api/deployments/:id +POST /api/deployments/:id/start +POST /api/deployments/:id/rollback +``` + +--- + +# 74. UI + +DevOS Settings 增加: + +```text +Settings +├── General +├── Environment +├── Configuration +├── Secrets +├── Runtime +├── Providers +├── Storage +├── Health +└── Deployments +``` + +Environment: + +```text +Development +Staging +Production +``` + +点击进入: + +```text +Overview +Configuration +Secrets +Services +Instances +Health +Deployments +Activity +``` + +--- + +# 75. Configuration UI + +页面: + +```text +Configuration +``` + +支持: + +```text +Search +Filter +Namespace +Environment +Modified +Secret +Restart Required +``` + +字段: + +```text +Key +Value +Source +Version +Last Modified +Status +``` + +Secret: + +```text +******** +``` + +绝不能默认显示: + +```text +plaintext +``` + +--- + +# 76. Runtime Dashboard + +显示: + +```text +API +Worker +Scheduler +Agent +MCP +``` + +例如: + +```text +API + ● Healthy + Version: 1.4.2 + Uptime: 4d 12h + +Worker + ● Healthy + Workers: 8 + Running Jobs: 21 + +Scheduler + ● Healthy + Schedules: 42 + +Agent + ● Healthy + Running: 3 +``` + +--- + +# 77. Health Dashboard + +显示: + +```text +Core +Database +Redis +Storage +Queue +Workers +Scheduler +Plugins +MCP +Agent +``` + +状态: + +```text +Healthy +Degraded +Unhealthy +``` + +支持点击进入详细信息。 + +--- + +# 78. Deployment Dashboard + +显示: + +```text +Current Version +Previous Version +Config Version +Plugin Versions +Deployment Status +Health +``` + +Timeline: + +```text +22:01 Validate +22:02 Migration +22:03 API started +22:04 Worker started +22:04 Health check +22:05 Healthy +``` + +--- + +# 79. Database Model + +至少增加: + +```text +environments +runtime_profiles +runtime_instances + +configuration_definitions +configuration_values +configuration_versions +configuration_changes + +secret_references + +deployments + +health_checks +health_results +``` + +建议: + +```text +configuration_values +``` + +不要直接保存所有 Secret。 + +--- + +# 80. Configuration Value Model + +```ts +interface ConfigurationValue { + id: string + + environmentId: string + + key: string + + value?: unknown + + secretRefId?: string + + source: + | 'default' + | 'file' + | 'env' + | 'database' + | 'secret' + | 'runtime' + + version: number + + createdAt: Date + + updatedAt: Date +} +``` + +--- + +# 81. Multi-Tenant Isolation + +如果 DevOS 支持 Organization: + +```text +System Configuration +Organization Configuration +Project Configuration +User Configuration +``` + +优先级: + +```text +User + ↓ +Project + ↓ +Organization + ↓ +Environment + ↓ +System + ↓ +Default +``` + +但: + +```text +Security Configuration +Encryption Configuration +Database Configuration +``` + +不能被普通 Project/User 覆盖。 + +--- + +# 82. Configuration Resolution + +最终: + +```ts +resolve( + key, + context +) +``` + +例如: + +```ts +config.get( + 'agent.defaultModel', + { + organizationId, + projectId, + environmentId + } +) +``` + +解析: + +```text +User + ↓ +Project + ↓ +Organization + ↓ +Environment + ↓ +System + ↓ +Default +``` + +返回最终值。 + +--- + +# 83. Configuration Explain + +必须提供: + +```text +config.explain(key) +``` + +例如: + +```text +agent.defaultModel + +Resolved Value: +gpt-x + +Source: +organization + +Environment: +production + +Version: +42 + +Overrides: +system = xxx +environment = xxx +organization = gpt-x +``` + +Secret: + +```text +Value: +[REDACTED] +``` + +--- + +# 84. Why Configuration Explain Is Important + +当用户问: + +> 为什么生产环境使用了这个 Model? + +DevOS 必须可以回答: + +```text +Value +Source +Version +Environment +Override +Changed By +Changed At +``` + +而不是: + +```text +不知道 +``` + +--- + +# 85. Local Development + +提供: + +```bash +devos dev +``` + +自动: + +```text +start postgres +start redis +start api +start worker +start scheduler +``` + +或者: + +```bash +devos dev api +devos dev worker +``` + +--- + +# 86. Bootstrap CLI + +提供: + +```bash +devos init +``` + +完成: + +```text +create config +create .env +check dependencies +initialize database +run migration +create default admin +create default environment +``` + +--- + +# 87. Environment Initialization + +首次启动: + +```text +No Environment + ↓ +Create local + ↓ +Generate Runtime Config + ↓ +Initialize Database + ↓ +Install Core Plugins + ↓ +Create Default Organization + ↓ +Ready +``` + +生产环境禁止自动创建: + +```text +random admin password +``` + +必须显式初始化。 + +--- + +# 88. Docker Environment + +`.env.example`: + +```text +DEVOS_ENV=development + +DEVOS_CORE_HTTP_HOST=0.0.0.0 +DEVOS_CORE_HTTP_PORT=3000 + +DEVOS_CORE_DATABASE_URL= +DEVOS_CORE_REDIS_URL= + +DEVOS_CORE_STORAGE_PROVIDER=local +DEVOS_CORE_STORAGE_PATH=/data/devos + +DEVOS_CORE_LOG_LEVEL=info +``` + +不要提交: + +```text +.env +.env.production +secret files +private keys +``` + +--- + +# 89. Security Rules + +必须禁止: + +```text +Secret in Git +Secret in logs +Secret in Task input +Secret in Agent memory +Secret in Event payload +Secret in Audit payload +Secret in Error message +Secret in telemetry +``` + +如果 Action Input 包含 Secret: + +必须进行: + +```text +redaction +``` + +--- + +# 90. Agent Memory Security + +Agent Memory 不允许保存: + +```text +API keys +passwords +tokens +cookies +private keys +session credentials +``` + +即使 Agent: + +```text +观察到 +``` + +也必须: + +```text +redact before persistence +``` + +--- + +# 91. Error Sanitization + +External API 返回: + +```text +authorization token +``` + +不能直接: + +```ts +throw new Error(response.text) +``` + +必须: + +```ts +sanitizeExternalError() +``` + +--- + +# 92. Configuration Validation + +启动时: + +```text +Configuration + ↓ +Schema Validation + ↓ +Cross-field Validation + ↓ +Dependency Validation +``` + +例如: + +```text +storage.provider = s3 +``` + +则必须: + +```text +s3.endpoint +s3.bucket +s3.region +credentials +``` + +全部满足。 + +--- + +# 93. Configuration Dependency + +配置定义支持: + +```ts +dependsOn?: string[] +``` + +以及: + +```ts +validate?: ( + config: ResolvedConfiguration +) => Promise +``` + +--- + +# 94. Fail Fast + +以下配置错误: + +```text +Database URL missing +Encryption key invalid +Redis URL invalid +Required Plugin configuration missing +``` + +Production: + +```text +启动失败 +``` + +不能: + +```text +启动后部分功能坏掉 +``` + +除非明确标记: + +```text +optional +``` + +--- + +# 95. Optional Dependencies + +Plugin 可以定义: + +```ts +dependencies: { + required: [], + optional: [] +} +``` + +例如: + +```text +SEO Plugin +required: + database + +optional: + browser + github +``` + +没有 Browser: + +```text +SEO Plugin +仍然可以启动 +``` + +但: + +```text +browser-dependent capabilities +``` + +标记: + +```text +unavailable +``` + +--- + +# 96. Capability Availability + +Capability Registry 必须知道: + +```ts +interface CapabilityAvailability { + available: boolean + + reason?: string + + requiredConfiguration?: string[] + + requiredProvider?: string[] + + health?: HealthResult +} +``` + +这样 Agent 不会尝试: + +```text +调用不可用 Capability +``` + +--- + +# 97. Runtime Dependency Graph + +DevOS 启动前可以构建: + +```text +API + ├── Config + ├── Database + ├── Resource + ├── Action + └── Plugin + +Worker + ├── Config + ├── Redis + ├── Queue + └── Action + +Agent + ├── Model Provider + ├── Capability Registry + └── Task Runtime +``` + +如果依赖不可用: + +```text +Runtime Profile +``` + +应报告明确原因。 + +--- + +# 98. Observability + +Runtime 必须输出: + +```text +Logs +Metrics +Traces +Health +Audit +Events +``` + +每一个 Instance: + +```text +instanceId +environmentId +runtimeVersion +``` + +都应该进入 Observability Context。 + +--- + +# 99. Metrics + +至少: + +```text +devos_runtime_instances + +devos_config_reload_total + +devos_config_validation_failures_total + +devos_health_check_total + +devos_deployment_total + +devos_deployment_duration + +devos_worker_active + +devos_worker_capacity + +devos_queue_depth +``` + +--- + +# 100. Events + +至少: + +```text +core.environment.created +core.environment.updated + +core.configuration.changed +core.configuration.reloaded +core.configuration.rollback + +core.secret.created +core.secret.rotated +core.secret.deleted + +core.runtime.started +core.runtime.ready +core.runtime.draining +core.runtime.stopped + +core.deployment.started +core.deployment.completed +core.deployment.failed +core.deployment.rollback + +core.health.degraded +core.health.recovered +``` + +--- + +# 101. Audit + +所有: + +```text +Configuration Change +Secret Change +Environment Change +Deployment +Rollback +Runtime Control +``` + +都必须 Audit。 + +例如: + +```text +User + ↓ +configuration.set + ↓ +key=agent.defaultModel + ↓ +environment=production + ↓ +version=42 +``` + +Secret: + +```text +key=provider.openai.apiKey +changed=true +``` + +而不是: + +```text +newValue=sk-xxxx +``` + +--- + +# 102. Resource Registry Integration + +新增: + +```text +core.environment +core.configuration +core.configurationVersion +core.secret +core.runtimeInstance +core.deployment +core.artifact +``` + +全部注册到: + +```text +Resource Registry +``` + +--- + +# 103. Action Runtime Integration + +所有操作: + +```text +Environment +Configuration +Secret +Runtime +Deployment +Artifact +``` + +必须: + +```text +Action Runtime +``` + +执行。 + +禁止: + +```text +Controller → Prisma +UI → API → Prisma +Plugin → Prisma +Agent → Prisma +``` + +--- + +# 104. Task Runtime Integration + +长任务: + +```text +Deployment +Configuration Migration +Artifact Cleanup +Environment Provision +``` + +必须: + +```text +Task → Job → Worker +``` + +例如: + +```text +Deployment Task + ├── validate + ├── migrate + ├── restart + ├── health check + └── finalize +``` + +--- + +# 105. Plugin Integration + +Plugin 可以声明: + +```ts +interface PluginManifest { + // existing... + + configuration?: ConfigurationDefinition[] + + secrets?: SecretDefinition[] + + providers?: ProviderDefinition[] + + healthChecks?: HealthCheckDefinition[] + + runtimeServices?: RuntimeService[] + + deploymentHooks?: DeploymentHook[] +} +``` + +这样 Plugin 能真正成为: + +```text +可安装 Runtime Extension +``` + +--- + +# 106. Plugin UI + +Plugin 可以注册: + +```text +Settings +Dashboard +Health +Configuration +Credentials +Runtime +``` + +例如: + +```text +Plugins +└── GitHub + ├── Overview + ├── Configuration + ├── Credentials + ├── Health + └── Usage +``` + +--- + +# 107. MCP Integration + +MCP Server 的配置: + +```text +mcp.github.endpoint +mcp.github.auth +mcp.github.timeout +``` + +必须通过: + +```text +Configuration Runtime +Secret Runtime +``` + +MCP Runtime 不允许自行: + +```text +process.env +``` + +获取业务 Secret。 + +--- + +# 108. MCP Health + +每个 MCP Server: + +```text +connected +degraded +disconnected +error +``` + +Agent Capability Discovery 必须过滤: + +```text +disconnected +``` + +的 MCP Capability。 + +--- + +# 109. Agent Model Provider + +Agent 使用: + +```text +ModelProvider +``` + +配置: + +```text +agent.defaultModel +agent.fallbackModel +agent.maxTokens +agent.temperature +``` + +Credential: + +```text +provider.openai.apiKey +``` + +进入: + +```text +Secret Runtime +``` + +--- + +# 110. Environment-Specific Model Policy + +例如: + +```text +development + cheap model + +staging + standard model + +production + production model +``` + +Agent Runtime: + +```ts +modelProvider.resolve({ + environmentId, + agentProfileId +}) +``` + +--- + +# 111. Production Freeze + +支持: + +```text +Environment Freeze +``` + +例如: + +```text +production +``` + +进入: + +```text +frozen +``` + +期间禁止: + +```text +configuration change +plugin upgrade +deployment +migration +``` + +除非: + +```text +override + approval +``` + +--- + +# 112. Environment Maintenance + +Environment 支持: + +```text +active +maintenance +inactive +``` + +Maintenance: + +```text +API + ↓ +正常读取 +``` + +但是: + +```text +新 Deployment +新 Agent Run +危险 Action +``` + +默认禁止。 + +--- + +# 113. Environment Actions + +```text +core.environment.create +core.environment.update +core.environment.activate +core.environment.deactivate +core.environment.maintenance +core.environment.freeze +core.environment.unfreeze +``` + +--- + +# 114. Production Approval + +结合 Agent / Action / Deployment: + +```text +Dangerous Action + ↓ +Policy + ↓ +requiresApproval + ↓ +Approval Resource + ↓ +Human Approval + ↓ +Task +``` + +禁止: + +```text +Agent + ↓ +production deployment +``` + +直接成功。 + +--- + +# 115. Disaster Recovery + +DevOS 必须定义: + +```text +Database Backup +Configuration Backup +Secret Backup +Artifact Backup +Plugin Lock +``` + +至少能够恢复: + +```text +Database ++ +Configuration Version ++ +Plugin Versions ++ +Runtime Version +``` + +--- + +# 116. Backup Resource + +```text +core.backup +``` + +```ts +interface Backup { + id: string + + environmentId: string + + type: + | 'database' + | 'configuration' + | 'artifact' + | 'full' + + status: + | 'pending' + | 'running' + | 'completed' + | 'failed' + + storageKey: string + + checksum?: string + + createdAt: Date +} +``` + +--- + +# 117. Backup Policy + +支持: + +```text +daily +weekly +monthly +before deployment +before migration +``` + +生产环境: + +```text +deployment + ↓ +backup + ↓ +migration +``` + +--- + +# 118. Recovery + +Recovery 必须使用 Task Runtime: + +```text +Recovery Task + ├── validate backup + ├── restore database + ├── restore configuration + ├── restore artifacts + ├── restore plugin versions + ├── health check + └── finalize +``` + +--- + +# 119. Filesystem Boundary + +禁止业务代码直接操作: + +```text +fs.writeFile('/etc/...') +``` + +必须使用: + +```text +RuntimePaths +StorageRuntime +ArtifactRuntime +``` + +只有明确标记的 Infrastructure Action 可以操作系统资源。 + +--- + +# 120. Shell Boundary + +DevOS Core 禁止业务代码随意: + +```ts +exec() +spawn() +``` + +需要系统命令时: + +```text +CommandRuntime +``` + +统一执行。 + +```ts +interface CommandRuntime { + execute( + command: string, + args: string[], + options?: CommandOptions + ): Promise +} +``` + +必须: + +```text +allowlist +timeout +cwd +environment isolation +stdout limit +stderr limit +audit +``` + +--- + +# 121. Command Security + +禁止: + +```text +shell=true +``` + +作为默认行为。 + +参数必须: + +```text +argv array +``` + +例如: + +```ts +execute( + 'git', + ['clone', url, target] +) +``` + +而不是: + +```ts +execute(`git clone ${url} ${target}`) +``` + +--- + +# 122. Container Runtime + +未来支持: + +```text +Docker +Podman +Kubernetes +``` + +抽象: + +```ts +interface ContainerRuntime { + create(...) + start(...) + stop(...) + restart(...) + remove(...) + logs(...) + inspect(...) +} +``` + +Plugin 可以使用: + +```text +container provider +``` + +但不能绕过: + +```text +Policy +Audit +Task Runtime +``` + +--- + +# 123. Infrastructure Provider + +统一: + +```text +InfrastructureProvider +``` + +未来: + +```text +AWS +Cloudflare +DigitalOcean +Hetzner +GCP +Azure +Kubernetes +Docker +SSH +``` + +例如: + +```ts +interface ServerProvider { + listServers(): Promise + + createServer(input): Promise + + deleteServer(id): Promise + + rebootServer(id): Promise +} +``` + +这些能力最终应该成为: + +```text +Plugin Capability +``` + +而不是 DevOS Core 硬编码。 + +--- + +# 124. Core vs Plugin Boundary + +DevOS Core 负责: + +```text +Configuration +Environment +Secret +Runtime +Health +Deployment abstraction +Storage abstraction +Provider abstraction +``` + +具体服务: + +```text +AWS +Cloudflare +GitHub +GitLab +OpenAI +Browser +SSH +Docker +``` + +应该: + +```text +Plugin +``` + +提供。 + +--- + +# 125. Project Configuration + +未来支持 Project: + +```text +Organization + ├── Project A + │ └── Environment + │ ├── dev + │ ├── staging + │ └── production + │ + └── Project B +``` + +Configuration Scope: + +```text +system +organization +project +environment +user +``` + +--- + +# 126. Configuration Context + +统一: + +```ts +interface ConfigurationContext { + environmentId?: string + + organizationId?: string + + projectId?: string + + userId?: string +} +``` + +--- + +# 127. Runtime Context + +统一: + +```ts +interface RuntimeContext { + runtimeInstanceId: string + + environmentId: string + + serviceType: RuntimeServiceType + + runtimeVersion: string + + configVersion: number + + shutdownSignal: AbortSignal +} +``` + +--- + +# 128. Package Structure + +Zcode 必须增加: + +```text +packages/ +├── config/ +├── secret/ +├── environment/ +├── runtime/ +├── health/ +├── deployment/ +├── storage/ +├── artifact/ +├── provider/ +└── command/ +``` + +建议: + +```text +packages/runtime/ +├── bootstrap/ +├── shutdown/ +├── instance/ +├── profile/ +├── paths/ +└── context/ +``` + +--- + +# 129. Config Package + +```text +packages/config/ +├── config-runtime.ts +├── config-registry.ts +├── config-resolver.ts +├── config-validator.ts +├── config-schema.ts +├── config-version.ts +├── config-store.ts +├── config-source.ts +├── config-redactor.ts +└── index.ts +``` + +--- + +# 130. Secret Package + +```text +packages/secret/ +├── secret-runtime.ts +├── secret-provider.ts +├── secret-store.ts +├── secret-encryption.ts +├── secret-redactor.ts +├── secret-context.ts +└── index.ts +``` + +--- + +# 131. Environment Package + +```text +packages/environment/ +├── environment-resource.ts +├── environment-service.ts +├── environment-policy.ts +├── environment-context.ts +└── index.ts +``` + +--- + +# 132. Health Package + +```text +packages/health/ +├── health-runtime.ts +├── health-check.ts +├── health-registry.ts +├── health-result.ts +└── index.ts +``` + +--- + +# 133. Deployment Package + +```text +packages/deployment/ +├── deployment-resource.ts +├── deployment-service.ts +├── deployment-runner.ts +├── deployment-policy.ts +├── deployment-plan.ts +└── index.ts +``` + +--- + +# 134. Provider Package + +```text +packages/provider/ +├── provider-registry.ts +├── provider-runtime.ts +├── model/ +├── storage/ +├── email/ +├── git/ +├── cloud/ +├── browser/ +└── index.ts +``` + +--- + +# 135. Command Package + +```text +packages/command/ +├── command-runtime.ts +├── command-policy.ts +├── command-parser.ts +├── command-result.ts +└── index.ts +``` + +--- + +# 136. Testing + +必须增加: + +```text +unit tests +integration tests +runtime tests +deployment tests +security tests +configuration tests +``` + +--- + +# 137. Configuration Tests + +必须测试: + +```text +default resolution +environment resolution +organization override +project override +user override + +schema validation +required config +optional config +secret config + +config version +config diff +config rollback + +reloadable config +restart-required config +``` + +--- + +# 138. Secret Tests + +必须测试: + +```text +encryption +decryption +rotation +redaction +access policy +audit +no plaintext logs +no plaintext events +no plaintext Agent memory +``` + +--- + +# 139. Environment Tests + +测试: + +```text +environment isolation +production policy +maintenance mode +freeze +activate +deactivate +``` + +--- + +# 140. Runtime Tests + +测试: + +```text +bootstrap order +dependency resolution +health +readiness +shutdown +worker drain +heartbeat +instance registration +``` + +--- + +# 141. Deployment Tests + +测试: + +```text +deployment plan +migration +health check +failure +rollback +backup +configuration version +plugin version +runtime version +``` + +--- + +# 142. Security Tests + +必须专门测试: + +```text +Agent cannot access secret +Plugin cannot access unrelated secret +User cannot access production config +Project cannot override system security config +MCP cannot bypass policy +Action cannot bypass environment policy +``` + +--- + +# 143. Acceptance Criteria + +完成本 Document 后必须满足: + +## Environment + +```text +[ ] Environment Resource +[ ] Environment isolation +[ ] Environment policy +[ ] Maintenance +[ ] Freeze +``` + +## Configuration + +```text +[ ] Configuration Registry +[ ] Configuration Runtime +[ ] Configuration Schema +[ ] Configuration Resolution +[ ] Configuration Version +[ ] Configuration Diff +[ ] Configuration Rollback +[ ] Configuration Explain +[ ] Configuration Reload +``` + +## Secret + +```text +[ ] Secret Runtime +[ ] Secret Provider +[ ] Encryption +[ ] Rotation +[ ] Redaction +[ ] Audit +``` + +## Runtime + +```text +[ ] Bootstrap +[ ] Shutdown +[ ] Runtime Profile +[ ] Runtime Instance +[ ] Heartbeat +[ ] Health +[ ] Liveness +[ ] Readiness +``` + +## Deployment + +```text +[ ] Deployment Resource +[ ] Deployment Task +[ ] Deployment Job +[ ] Migration +[ ] Health Check +[ ] Rollback +[ ] Backup +``` + +## Infrastructure + +```text +[ ] Storage Runtime +[ ] Artifact Runtime +[ ] Provider Registry +[ ] Command Runtime +[ ] Container Runtime abstraction +``` + +## Integration + +```text +[ ] Action Runtime +[ ] Task Runtime +[ ] Agent Runtime +[ ] Plugin Runtime +[ ] MCP Runtime +[ ] Capability Registry +[ ] Audit +[ ] Event +[ ] Observability +``` + +--- + +# 144. Zcode Implementation Rules + +## Rule 1 + +禁止业务代码直接读取: + +```text +process.env +``` + +必须: + +```text +ConfigurationRuntime +``` + +--- + +## Rule 2 + +禁止业务代码直接读取 Secret。 + +必须: + +```text +SecretRuntime +``` + +--- + +## Rule 3 + +禁止 Secret 出现在: + +```text +Log +Event +Audit +Task Input +Agent Memory +Error +Metric +Trace +``` + +--- + +## Rule 4 + +禁止 Controller 直接: + +```text +Prisma +Redis +fs +exec +fetch +``` + +必须通过: + +```text +Resource +Action +Runtime +Provider +``` + +--- + +## Rule 5 + +部署必须: + +```text +Task → Job → Worker +``` + +--- + +## Rule 6 + +Migration 必须: + +```text +Migration Runtime ++ +Distributed Lock +``` + +--- + +## Rule 7 + +所有 Runtime Instance 必须: + +```text +register +heartbeat +health +shutdown +``` + +--- + +## Rule 8 + +Production 必须拥有更严格的: + +```text +Policy +Approval +Audit +Backup +Rollback +``` + +--- + +## Rule 9 + +Plugin 可以扩展: + +```text +Configuration +Secret +Provider +Health +Runtime Service +UI +``` + +但不能修改: + +```text +DevOS Core Security Boundary +``` + +--- + +## Rule 10 + +Agent 不得绕过: + +```text +Environment Policy +Configuration Policy +Secret Policy +Action Policy +Deployment Policy +``` + +--- + +# 145. Golden Rule + +DevOS 的 Infrastructure Runtime 必须遵循: + +```text +Environment + ↓ +Configuration + ↓ +Secret + ↓ +Runtime + ↓ +Provider + ↓ +Health + ↓ +Deployment +``` + +业务执行必须继续遵循: + +```text +Goal + ↓ +Agent + ↓ +Skill + ↓ +Capability + ↓ +Task + ↓ +Job + ↓ +Action + ↓ +Action Runtime + ↓ +Execution +``` + +最终 DevOS 的完整运行模型: + +```text + DevOS + │ + ┌──────────────────┼──────────────────┐ + │ │ │ + Runtime Application Agent + │ │ │ + Environment Resource Goal + Configuration Action │ + Secret Event Skill + Provider │ │ + Health └──────────┬─────────┘ + Deployment │ + │ Capability + │ │ + └──────────────┬────────────┘ + │ + Action Runtime + │ + Task + │ + Job + │ + Worker + │ + Execution + │ + Event + │ + Observation +``` + +--- + +# 146. Final Principle + +DevOS 不应该让每一个新项目重新解决: + +```text +.env +Secrets +Docker +Redis +Postgres +Worker +Scheduler +Health +Deployment +Migration +Storage +Providers +Configuration +Runtime +``` + +这些应该全部成为: + +```text +DevOS Platform +``` + +而业务项目只需要: + +```text +Resource +Action +Event +Plugin +Skill +Agent +UI +``` + +例如一个新的 SEO 应用: + +```text +DevOS Core ++ +SEO Plugin ++ +SEO Skills ++ +SEO Agents +``` + +而不是重新建立: + +```text +SEO Backend +SEO Queue +SEO Worker +SEO Config +SEO Secrets +SEO Scheduler +SEO Deployment +SEO Agent Runtime +``` + +**DevOS 的目标是让“业务项目”只负责业务,让“平台”负责运行。** + + +这一篇完成后,DevOS 的基础设施边界就比较完整了:**03 Resource/Action → 06 Agent/MCP/Skill → 09 Task/Job → 12 Version/Migration → 13 Deployment/Environment/Config**。 diff --git a/Docs/DevOS-Platform-v2/14_DATA_QUERY_SEARCH_INDEX_RUNTIME.md b/Docs/DevOS-Platform-v2/14_DATA_QUERY_SEARCH_INDEX_RUNTIME.md new file mode 100644 index 0000000..c0b34ce --- /dev/null +++ b/Docs/DevOS-Platform-v2/14_DATA_QUERY_SEARCH_INDEX_RUNTIME.md @@ -0,0 +1,5062 @@ + +# DevOS Data / Query / Search / Index Runtime + +> Document: 14 +> Status: Required +> Audience: Zcode / DevOS Core Team +> Depends On: +> - 03_RESOURCE_ACTION_MODEL.md +> - 06_MCP_SKILL_AGENT_RUNTIME.md +> - 09_TASK_JOB_QUEUE_RUNTIME.md +> - 12_MIGRATION_VERSIONING_COMPATIBILITY.md +> - 13_DEPLOYMENT_ENVIRONMENT_CONFIG_RUNTIME.md + +--- + +# 1. Goals + +DevOS 已经拥有: + +- Resource +- Action +- Event +- Agent +- Skill +- MCP +- Task +- Job +- Queue +- Worker +- Configuration +- Environment +- Deployment + +下一步必须解决: + +> DevOS 中的数据应该如何被统一访问、查询、过滤、排序、搜索、聚合和索引? + +否则最终会出现: + +```text +UI → Prisma +Plugin → Prisma +Agent → Prisma +MCP → Prisma +Action → Prisma +Search → Elasticsearch +Plugin Search → 自己实现 +```` + +最终形成多个数据访问体系。 + +本 Document 要建立: + +```text +Data Runtime +Query Runtime +Repository Runtime +Search Runtime +Index Runtime +Filter Runtime +Pagination Runtime +Relation Runtime +``` + +最终原则: + +```text +Resource + ↓ +Data Definition + ↓ +Repository / Query + ↓ +Data Runtime + ↓ +Database / Search Index +``` + +--- + +# 2. Core Principle + +DevOS 必须区分: + +```text +Resource +Data +Query +Search +Index +Action +``` + +它们不是同一个东西。 + +--- + +# 3. Resource + +Resource 表示: + +> 系统中的业务对象。 + +例如: + +```text +core.user +core.organization +core.project +core.task + +seo.website +seo.article + +devops.server +devops.deployment +``` + +--- + +# 4. Data + +Data 表示: + +> Resource 当前保存的数据。 + +例如: + +```json +{ + "id": "website_123", + "domain": "example.com", + "status": "active" +} +``` + +--- + +# 5. Query + +Query 表示: + +> 从结构化数据中获取数据。 + +例如: + +```text +所有 active website +最近创建的 20 个 Task +某个 Organization 的 Users +``` + +--- + +# 6. Search + +Search 表示: + +> 根据文本、语义、字段权重等进行相关性检索。 + +例如: + +```text +搜索: +"关于 AI SEO 的文章" + +返回: +Article 1 +Article 2 +Website 3 +Task 4 +``` + +--- + +# 7. Index + +Index 表示: + +> 为 Query / Search 提供高效读取结构。 + +数据库 Index: + +```text +B-Tree +GIN +GiST +``` + +搜索 Index: + +```text +Full Text +Vector +Hybrid +``` + +--- + +# 8. Architecture + +```text + Resource + │ + Resource Schema + │ + ┌────────────┴────────────┐ + │ │ + Data Runtime Search Runtime + │ │ + Repository Runtime Index Runtime + │ │ + ┌─────┴──────┐ ┌───────┴───────┐ + │ │ │ │ + PostgreSQL Cache Full Text Vector + Index Index +``` + +--- + +# 9. Data Runtime + +统一入口: + +```ts +export interface DataRuntime { + repository( + resource: string, + context: DataContext + ): Repository + + query( + resource: string, + query: QueryInput, + context: DataContext + ): Promise> + + count( + resource: string, + query: QueryInput, + context: DataContext + ): Promise + + exists( + resource: string, + query: QueryInput, + context: DataContext + ): Promise +} +``` + +--- + +# 10. DataContext + +所有数据访问必须携带 Context。 + +```ts +export interface DataContext { + requestId: string + + actor: Actor + + organizationId?: string + + projectId?: string + + environmentId?: string + + permissions: string[] + + metadata?: Record +} +``` + +禁止: + +```ts +repository.findMany() +``` + +在没有: + +```text +actor +organization +scope +``` + +的情况下访问业务数据。 + +--- + +# 11. Repository + +Repository 是 Resource 的结构化数据访问接口。 + +```ts +export interface Repository { + findById( + id: string + ): Promise + + findMany( + query: QueryInput + ): Promise> + + count( + query: QueryInput + ): Promise + + exists( + query: QueryInput + ): Promise +} +``` + +注意: + +Repository 默认只负责: + +```text +读取 +``` + +写入仍然应该通过: + +```text +Action Runtime +``` + +--- + +# 12. Important Rule + +禁止: + +```text +UI + ↓ +Repository + ↓ +UPDATE database +``` + +应该: + +```text +UI + ↓ +Action + ↓ +Action Runtime + ↓ +Repository / Domain Service + ↓ +Database +``` + +--- + +# 13. Read vs Write + +DevOS 可以采用: + +```text +CQRS-lite +``` + +即: + +```text +Read + ↓ +Query / Repository + +Write + ↓ +Action Runtime +``` + +不需要一开始实现完整 CQRS/Event Sourcing。 + +--- + +# 14. Query Input + +```ts +export interface QueryInput { + select?: string[] + + filter?: FilterNode + + sort?: SortRule[] + + pagination?: PaginationInput + + include?: IncludeRule[] + + search?: SearchInput + + groupBy?: string[] + + aggregates?: AggregateRule[] + + distinct?: boolean +} +``` + +--- + +# 15. Filter + +Filter 是 DevOS 非常重要的统一抽象。 + +例如: + +```text +status = active +``` + +```ts +{ + field: 'status', + operator: 'eq', + value: 'active' +} +``` + +--- + +# 16. Filter Operators + +至少支持: + +```text +eq +neq +gt +gte +lt +lte + +in +notIn + +contains +startsWith +endsWith + +isNull +isNotNull + +between + +exists +``` + +--- + +# 17. Filter Tree + +复杂查询: + +```text +status = active +AND +( + score > 80 + OR + backlinks > 100 +) +``` + +表示: + +```ts +{ + and: [ + { + field: 'status', + operator: 'eq', + value: 'active' + }, + { + or: [ + { + field: 'score', + operator: 'gt', + value: 80 + }, + { + field: 'backlinks', + operator: 'gt', + value: 100 + } + ] + } + ] +} +``` + +--- + +# 18. Filter Schema + +```ts +export type FilterNode = + | FilterCondition + | FilterGroup + +export interface FilterCondition { + field: string + + operator: + | 'eq' + | 'neq' + | 'gt' + | 'gte' + | 'lt' + | 'lte' + | 'in' + | 'notIn' + | 'contains' + | 'startsWith' + | 'endsWith' + | 'isNull' + | 'isNotNull' + | 'between' + + value?: unknown +} + +export interface FilterGroup { + and?: FilterNode[] + + or?: FilterNode[] + + not?: FilterNode +} +``` + +--- + +# 19. Security: Filter Fields + +用户不能任意查询数据库字段。 + +Resource 必须声明: + +```ts +export interface FieldDefinition { + name: string + + type: FieldType + + readable?: boolean + + writable?: boolean + + searchable?: boolean + + sortable?: boolean + + filterable?: boolean + + sensitive?: boolean +} +``` + +例如: + +```text +passwordHash +``` + +必须: + +```text +readable = false +searchable = false +filterable = false +``` + +--- + +# 20. Field Types + +至少: + +```text +string +text +integer +float +decimal +boolean +date +datetime +json +uuid +enum +relation +array +``` + +未来: + +```text +vector +geometry +binary +``` + +--- + +# 21. Resource Schema + +Resource 应定义 Schema: + +```ts +export interface ResourceSchema { + resource: string + + version: string + + fields: FieldDefinition[] + + relations?: RelationDefinition[] + + indexes?: IndexDefinition[] + + search?: SearchDefinition + + validation?: unknown +} +``` + +--- + +# 22. Resource Schema Example + +```ts +const websiteSchema: ResourceSchema = { + resource: 'seo.website', + + version: '1.0', + + fields: [ + { + name: 'id', + type: 'uuid', + readable: true + }, + { + name: 'domain', + type: 'string', + readable: true, + searchable: true, + sortable: true, + filterable: true + }, + { + name: 'status', + type: 'enum', + readable: true, + filterable: true, + sortable: true + } + ] +} +``` + +--- + +# 23. Pagination + +统一支持: + +```text +offset pagination +cursor pagination +``` + +--- + +# 24. Offset Pagination + +```ts +export interface OffsetPagination { + type: 'offset' + + page: number + + pageSize: number +} +``` + +返回: + +```ts +{ + items: [], + page: 1, + pageSize: 20, + total: 1234 +} +``` + +适合: + +```text +Admin UI +Reports +Tables +``` + +--- + +# 25. Cursor Pagination + +```ts +export interface CursorPagination { + type: 'cursor' + + cursor?: string + + limit: number + + direction?: 'forward' | 'backward' +} +``` + +返回: + +```ts +{ + items: [], + nextCursor: '...', + hasMore: true +} +``` + +适合: + +```text +Agent +Activity Feed +Events +Logs +Large datasets +``` + +--- + +# 26. Pagination Limits + +系统必须限制: + +```text +maxPageSize +maxOffset +maxQueryCost +``` + +默认: + +```text +pageSize <= 100 +``` + +Agent / MCP: + +```text +更严格 +``` + +禁止: + +```text +pageSize = 1000000 +``` + +--- + +# 27. Sort + +```ts +export interface SortRule { + field: string + + direction: 'asc' | 'desc' +} +``` + +例如: + +```text +createdAt desc +score desc +domain asc +``` + +--- + +# 28. Sort Security + +只有: + +```text +sortable = true +``` + +的字段才能排序。 + +禁止用户: + +```text +ORDER BY arbitrary SQL +``` + +--- + +# 29. Include + +支持 Resource Relation: + +```text +Task + └── Jobs +``` + +查询: + +```ts +{ + include: [ + { + relation: 'jobs' + } + ] +} +``` + +但是必须防止: + +```text +N+1 query +``` + +--- + +# 30. Relations + +统一: + +```ts +export interface RelationDefinition { + name: string + + target: string + + type: + | 'one' + | 'many' + + foreignKey?: string + + targetKey?: string + + readable?: boolean +} +``` + +--- + +# 31. Relation Examples + +```text +core.organization + └── users + +core.task + └── jobs + +core.job + └── executions + +seo.website + └── articles +``` + +--- + +# 32. Relation Permission + +Relation 也需要权限。 + +例如: + +```text +User +``` + +可以看到: + +```text +Organization +``` + +但不能自动: + +```text +Organization + ↓ +all users +``` + +除非: + +```text +relation.read +``` + +允许。 + +--- + +# 33. Query Authorization + +Query Runtime 必须执行: + +```text +Actor Permission ++ +Resource Permission ++ +Field Permission ++ +Scope Policy ++ +Filter Policy +``` + +最终才生成: + +```text +Database Query +``` + +--- + +# 34. Row-Level Security + +某些 Resource 需要 Row Scope。 + +例如: + +```text +organizationId = currentOrganization +``` + +必须由 Runtime 自动注入。 + +不能依赖前端: + +```text +?organizationId=xxx +``` + +--- + +# 35. Scope Provider + +```ts +export interface ScopeProvider { + resolve( + resource: string, + context: DataContext + ): Promise +} +``` + +例如: + +```text +core.task +``` + +自动添加: + +```text +organizationId = currentOrganization +``` + +--- + +# 36. Scope Composition + +最终: + +```text +User Filter +AND +Organization Scope +AND +Project Scope +AND +Environment Scope +AND +Policy Scope +``` + +例如: + +```text +User: +status = failed + +System: +organizationId = org_1 + +Project: +projectId = project_2 +``` + +最终: + +```text +status = failed +AND organizationId = org_1 +AND projectId = project_2 +``` + +--- + +# 37. Query Compilation + +Query Runtime: + +```text +QueryInput + ↓ +Validate + ↓ +Authorize + ↓ +Inject Scope + ↓ +Resolve Relations + ↓ +Optimize + ↓ +Compile + ↓ +Database Query +``` + +--- + +# 38. SQL Boundary + +禁止: + +```text +Agent +Plugin +MCP +UI +``` + +直接发送: + +```text +raw SQL +``` + +只有: + +```text +Data Runtime +``` + +可以执行 SQL。 + +--- + +# 39. Raw SQL + +Core 可以在极少数 Infrastructure 场景使用: + +```ts +data.rawQuery(...) +``` + +但必须: + +```text +internal only +``` + +不能暴露: + +```text +MCP +REST +Agent +Plugin public API +``` + +--- + +# 40. Query Cost + +每一个 Query 应估算成本: + +```ts +export interface QueryCost { + estimatedRows: number + + joins: number + + sortCost: number + + searchCost: number + + totalScore: number +} +``` + +高成本 Query: + +```text +reject +``` + +或: + +```text +require async Task +``` + +--- + +# 41. Large Query + +例如: + +```text +导出 100 万条数据 +``` + +不能: + +```text +HTTP Request + ↓ +Query + ↓ +return 1M rows +``` + +应该: + +```text +Export Action + ↓ +Task + ↓ +Job + ↓ +Worker + ↓ +Cursor Query + ↓ +Artifact +``` + +--- + +# 42. Data Export + +统一 Resource: + +```text +core.export +``` + +Action: + +```text +core.export.create +core.export.cancel +core.export.download +``` + +支持: + +```text +CSV +JSON +JSONL +Excel +``` + +--- + +# 43. Export Security + +Export 必须使用: + +```text +same permission +same scope +same field security +``` + +不能: + +```text +UI Query +``` + +没有权限: + +```text +passwordHash +``` + +但: + +```text +Export +``` + +却把它导出来。 + +--- + +# 44. Search Runtime + +统一: + +```ts +export interface SearchRuntime { + search( + resource: string, + input: SearchInput, + context: DataContext + ): Promise> + + suggest( + resource: string, + input: SuggestInput, + context: DataContext + ): Promise +} +``` + +--- + +# 45. Search Input + +```ts +export interface SearchInput { + query: string + + fields?: string[] + + filter?: FilterNode + + sort?: SortRule[] + + pagination?: PaginationInput + + mode?: + | 'fulltext' + | 'semantic' + | 'hybrid' + + minScore?: number +} +``` + +--- + +# 46. Search Modes + +## Full Text + +```text +keyword +token +phrase +field weight +``` + +## Semantic + +```text +embedding +vector similarity +``` + +## Hybrid + +```text +Full Text ++ +Vector ++ +Ranking +``` + +DevOS 推荐最终: + +```text +hybrid +``` + +--- + +# 47. Search Provider + +抽象: + +```ts +export interface SearchProvider { + index( + document: SearchDocument + ): Promise + + delete( + id: string + ): Promise + + search( + input: SearchProviderInput + ): Promise + + health(): Promise +} +``` + +--- + +# 48. Search Provider Implementations + +第一阶段: + +```text +PostgreSQL Full Text +``` + +可选: + +```text +OpenSearch +Elasticsearch +Meilisearch +Typesense +``` + +Vector: + +```text +pgvector +``` + +优先使用: + +```text +PostgreSQL + pgvector +``` + +减少基础设施复杂度。 + +--- + +# 49. Search Index + +Resource 可以声明: + +```ts +export interface SearchDefinition { + enabled: boolean + + fields: SearchField[] + + provider?: string + + vector?: { + enabled: boolean + + dimensions: number + + model?: string + } +} +``` + +--- + +# 50. Search Field + +```ts +export interface SearchField { + field: string + + weight?: number + + searchable?: boolean + + vectorizable?: boolean + + stored?: boolean +} +``` + +例如: + +```text +title weight=10 +description weight=5 +content weight=2 +``` + +--- + +# 51. Search Document + +```ts +export interface SearchDocument { + id: string + + resource: string + + resourceId: string + + fields: Record + + text?: string + + vector?: number[] + + metadata?: Record + + version: string + + indexedAt: Date +} +``` + +--- + +# 52. Index Isolation + +Index 必须包含: + +```text +organizationId +projectId +environmentId +resource +``` + +防止: + +```text +Org A +``` + +搜索到: + +```text +Org B +``` + +的数据。 + +--- + +# 53. Search Permission + +搜索结果必须再次执行: + +```text +Permission ++ +Scope +``` + +不能认为: + +```text +Index = authorized data +``` + +因为权限可能发生变化。 + +--- + +# 54. Search Flow + +```text +User + ↓ +Search Action + ↓ +Search Runtime + ↓ +Permission + ↓ +Scope + ↓ +Search Provider + ↓ +Result + ↓ +Permission Recheck + ↓ +Return +``` + +--- + +# 55. Search Ranking + +基础: + +```text +text relevance +field weight +freshness +exact match +``` + +未来: + +```text +business score +authority +quality +user preference +``` + +--- + +# 56. Hybrid Ranking + +例如: + +```text +finalScore = + textScore * 0.4 + + + vectorScore * 0.4 + + + businessScore * 0.2 +``` + +权重必须由: + +```text +Search Definition +``` + +定义。 + +--- + +# 57. Semantic Search + +Agent 可以: + +```text +搜索: +“寻找高质量 AI SEO 文章” +``` + +转换: + +```text +embedding + ↓ +vector search + ↓ +metadata filter + ↓ +ranking +``` + +--- + +# 58. Agent Search + +Agent 不应该获取: + +```text +10000 records +``` + +而应该: + +```text +Search Runtime + ↓ +topK +``` + +例如: + +```text +topK = 10 +``` + +--- + +# 59. Capability Discovery Search + +结合: + +```text +06_MCP_SKILL_AGENT_RUNTIME.md +``` + +Capability Registry 也可以使用: + +```text +Search Runtime +``` + +搜索: + +```text +Capability +Skill +Plugin +MCP +Action +``` + +--- + +# 60. Search as Capability + +Search 本身也是: + +```text +Capability +``` + +例如: + +```text +core.search +``` + +但 Agent 获取搜索能力时: + +```text +Search +``` + +必须根据: + +```text +Permission +Scope +Budget +``` + +限制。 + +--- + +# 61. Index Lifecycle + +Index 状态: + +```text +pending +building +ready +degraded +rebuilding +failed +``` + +--- + +# 62. Index Resource + +```text +core.searchIndex +``` + +```ts +export interface SearchIndex { + id: string + + resource: string + + provider: string + + status: + | 'pending' + | 'building' + | 'ready' + | 'degraded' + | 'rebuilding' + | 'failed' + + documentCount: number + + version: string + + lastIndexedAt?: Date + + error?: string +} +``` + +--- + +# 63. Index Actions + +```text +core.searchIndex.create +core.searchIndex.rebuild +core.searchIndex.pause +core.searchIndex.resume +core.searchIndex.delete +core.searchIndex.health +``` + +--- + +# 64. Rebuild + +Index 重建必须: + +```text +Task + ↓ +Job + ↓ +Worker + ↓ +Cursor Query + ↓ +Batch Index +``` + +不能: + +```text +HTTP Request + ↓ +全部读取 + ↓ +全部 Index +``` + +--- + +# 65. Incremental Index + +Resource 数据变化时: + +```text +Resource Changed + ↓ +Event + ↓ +Index Job + ↓ +Update Index +``` + +例如: + +```text +seo.website.updated +``` + +触发: + +```text +search.index.update +``` + +--- + +# 66. Outbox + +数据库写入: + +```text +Transaction + ├── Update Resource + └── Insert Outbox Event +``` + +然后: + +```text +Outbox + ↓ +Worker + ↓ +Search Index +``` + +防止: + +```text +DB updated +but index not updated +``` + +--- + +# 67. Index Consistency + +DevOS 默认: + +```text +Database = Source of Truth +Search Index = Derived State +``` + +因此: + +```text +Index corrupted +``` + +可以: + +```text +Rebuild +``` + +而不会丢失业务数据。 + +--- + +# 68. Cache Runtime + +Data Runtime 可以使用: + +```text +Cache Runtime +``` + +```ts +export interface CacheRuntime { + get(key: string): Promise + + set( + key: string, + value: T, + options?: CacheOptions + ): Promise + + delete(key: string): Promise + + invalidate(prefix: string): Promise +} +``` + +--- + +# 69. Cache Rules + +缓存只能是: + +```text +derived data +``` + +不能作为: + +```text +source of truth +``` + +--- + +# 70. Cache Key + +必须包含: + +```text +resource +query +scope +configuration version +``` + +例如: + +```text +devos: +query: +seo.website: +org_1: +hash(...) +``` + +避免: + +```text +Org A cache +``` + +被: + +```text +Org B +``` + +使用。 + +--- + +# 71. Query Cache Invalidation + +Resource 更新: + +```text +Action + ↓ +Event + ↓ +Cache Invalidation +``` + +例如: + +```text +seo.website.updated +``` + +触发: + +```text +invalidate seo.website +``` + +--- + +# 72. Data Loader + +防止 N+1: + +```ts +export interface DataLoader { + load(key: K): Promise + + loadMany(keys: K[]): Promise +} +``` + +Relation Runtime 应使用: + +```text +batch loading +``` + +--- + +# 73. Query Observability + +每个 Query 记录: + +```text +requestId +resource +operation +duration +rows +queryCost +cacheHit +provider +``` + +不能记录: + +```text +Secret +Sensitive values +``` + +--- + +# 74. Slow Query Detection + +配置: + +```text +query.slowThresholdMs +``` + +例如: + +```text +> 500ms +``` + +产生: + +```text +core.query.slow +``` + +Event / Metric。 + +--- + +# 75. Query Timeout + +每个 Query 必须有: + +```text +timeout +``` + +例如: + +```ts +{ + timeoutMs: 5000 +} +``` + +超时: + +```text +cancel +``` + +而不是无限等待。 + +--- + +# 76. Query Cancellation + +Data Runtime 必须支持: + +```ts +interface QueryOptions { + signal?: AbortSignal +} +``` + +Agent / Task 取消时: + +```text +Agent + ↓ +Task Cancel + ↓ +Job Cancel + ↓ +Query Abort +``` + +--- + +# 77. Query Transactions + +复杂 Action: + +```text +Action + ↓ +Transaction + ├── read + ├── validate + ├── write + └── event +``` + +Transaction 生命周期不能跨: + +```text +HTTP request +Task +Worker +Agent iteration +``` + +过长时间。 + +--- + +# 78. Optimistic Lock + +需要支持: + +```ts +version +updatedAt +``` + +例如: + +```text +Update Website +where id=123 +and version=4 +``` + +成功: + +```text +version=5 +``` + +失败: + +```text +Conflict +``` + +--- + +# 79. Data Conflict + +返回: + +```ts +export interface DataConflictError { + type: 'conflict' + + resource: string + + resourceId: string + + expectedVersion: number + + actualVersion: number +} +``` + +UI: + +```text +数据已被其他用户修改。 +``` + +Agent: + +```text +re-read +→ +re-plan +``` + +--- + +# 80. Soft Delete + +Resource 可以定义: + +```ts +deletion: { + strategy: + | 'hard' + | 'soft' +} +``` + +Soft delete: + +```text +deletedAt +``` + +默认 Query: + +```text +deletedAt IS NULL +``` + +--- + +# 81. Restore + +Soft Delete Resource: + +```text +restore +``` + +Action: + +```text +resource.restore +``` + +必须重新经过: + +```text +Authorization +Scope +Validation +``` + +--- + +# 82. Archive + +Archive 和 Delete 必须区分: + +```text +active +archived +deleted +``` + +Archive: + +```text +仍然存在 +但默认不出现在普通 Query +``` + +--- + +# 83. Data Lifecycle + +Resource 可以定义: + +```ts +export interface DataLifecycle { + retentionDays?: number + + archiveAfterDays?: number + + deleteAfterDays?: number +} +``` + +例如: + +```text +Execution + ├── 30 days → archive + └── 180 days → delete +``` + +--- + +# 84. Lifecycle Worker + +数据生命周期由: + +```text +Scheduler + ↓ +Task + ↓ +Job + ↓ +Worker +``` + +执行。 + +禁止: + +```text +API startup + ↓ +delete old records +``` + +--- + +# 85. Data Retention Policy + +Production 必须支持: + +```text +Audit retention +Execution retention +Log retention +Artifact retention +Event retention +``` + +不同类型可以独立配置。 + +--- + +# 86. Privacy + +未来如果系统保存用户个人数据: + +Resource 必须声明: + +```ts +privacy?: { + pii: boolean + + fields?: string[] + + retentionDays?: number +} +``` + +PII 字段: + +```text +redaction +access policy +export policy +``` + +必须更严格。 + +--- + +# 87. Data Masking + +支持: + +```text +email +phone +address +token +credential +``` + +显示: + +```text +u***@example.com +``` + +而不是: + +```text +full value +``` + +--- + +# 88. Generic CRUD + +对于简单 Resource: + +```text +list +get +create +update +delete +``` + +可以自动生成。 + +但是: + +```text +Generic CRUD +``` + +只能作为: + +```text +Resource Action Generator +``` + +不能绕过: + +```text +Action Runtime +``` + +--- + +# 89. Resource Query API + +推荐: + +```text +GET /api/resources/:resource +GET /api/resources/:resource/:id +POST /api/resources/:resource/query +``` + +但必须: + +```text +Resource Registry + ↓ +Schema + ↓ +Permission + ↓ +Query Runtime +``` + +--- + +# 90. Generic Query Example + +```json +{ + "filter": { + "and": [ + { + "field": "status", + "operator": "eq", + "value": "active" + } + ] + }, + "sort": [ + { + "field": "createdAt", + "direction": "desc" + } + ], + "pagination": { + "type": "cursor", + "limit": 20 + } +} +``` + +--- + +# 91. Generic Search API + +```text +POST /api/search +``` + +请求: + +```json +{ + "resource": "seo.website", + "query": "AI SEO", + "mode": "hybrid", + "limit": 10 +} +``` + +返回: + +```json +{ + "items": [], + "nextCursor": "...", + "totalApproximate": 100 +} +``` + +--- + +# 92. Search Across Resources + +支持: + +```text +POST /api/search/global +``` + +例如: + +```text +query: +"Cloudflare production" +``` + +搜索: + +```text +Website +Server +Deployment +Task +Plugin +Document +``` + +但是必须: + +```text +permission filtered +``` + +--- + +# 93. Global Search Registry + +```ts +export interface GlobalSearchSource { + resource: string + + priority: number + + searchableFields: string[] + + transform( + item: unknown + ): SearchDocument +} +``` + +Plugin 可以注册: + +```text +global search source +``` + +--- + +# 94. Plugin Search + +Plugin 可以声明: + +```ts +search?: { + enabled: boolean + + fields: SearchField[] +} +``` + +安装后: + +```text +Plugin + ↓ +Search Registry + ↓ +Global Search +``` + +自动可搜索。 + +--- + +# 95. MCP Search + +MCP 可以调用: + +```text +core.search +``` + +而不是: + +```text +MCP → Database +``` + +MCP 搜索: + +```text +permission ++ +scope ++ +budget +``` + +必须全部有效。 + +--- + +# 96. Agent Query vs Search + +Agent 应优先: + +```text +Search +``` + +而不是: + +```text +Query all +``` + +例如: + +```text +找 10 个最相关网站 +``` + +使用: + +```text +Search topK=10 +``` + +而不是: + +```text +Query all websites +``` + +--- + +# 97. Agent Structured Query + +如果目标明确: + +```text +查找 status=failed 的任务 +``` + +使用: + +```text +Query +``` + +而不是: + +```text +LLM semantic search +``` + +规则: + +```text +Structured requirement + → Query + +Natural language requirement + → Search +``` + +--- + +# 98. Search Progressive Disclosure + +Agent Search Tool Schema: + +```text +Level 1: +search(resource, query) + +Level 2: +filters +fields +ranking + +Level 3: +advanced search +``` + +不要一次把: + +```text +所有 Search Schema +``` + +发送给模型。 + +--- + +# 99. Data Capability + +Data Runtime 暴露: + +```text +Query +Search +Count +Exists +Aggregate +Export +``` + +作为: + +```text +Capabilities +``` + +例如: + +```text +core.resource.query +core.resource.search +core.resource.aggregate +core.resource.export +``` + +--- + +# 100. Aggregate + +支持: + +```text +count +sum +avg +min +max +``` + +例如: + +```text +统计: +过去 7 天失败 Task 数量 +``` + +不要读取所有 Task: + +```text +Query all + ↓ +Agent count +``` + +而应该: + +```text +Aggregate +``` + +--- + +# 101. Aggregate Definition + +```ts +export interface AggregateRule { + field?: string + + function: + | 'count' + | 'sum' + | 'avg' + | 'min' + | 'max' + + alias: string +} +``` + +--- + +# 102. Group By + +例如: + +```text +按 status 统计 Task +``` + +```ts +{ + groupBy: ['status'], + aggregates: [ + { + function: 'count', + alias: 'count' + } + ] +} +``` + +--- + +# 103. Aggregate Security + +Aggregate 也必须: + +```text +permission +scope +field policy +``` + +例如: + +```text +salary +``` + +不能因为: + +```text +AVG(salary) +``` + +就绕过: + +```text +salary field permission +``` + +--- + +# 104. Query Builder + +UI 可以提供: + +```text +Filter Builder +Sort Builder +Group Builder +Search +``` + +例如: + +```text +Status [is] Failed +AND +Created At [after] 2026-09-01 +``` + +最终生成: + +```text +QueryInput +``` + +--- + +# 105. Saved Query + +用户可以保存: + +```text +Saved Query +``` + +Resource: + +```text +core.savedQuery +``` + +```ts +interface SavedQuery { + id: string + + resource: string + + name: string + + query: QueryInput + + ownerId: string + + scope: 'private' | 'organization' | 'project' + + createdAt: Date +} +``` + +--- + +# 106. Saved Search + +类似: + +```text +core.savedSearch +``` + +可以保存: + +```text +query +filters +sort +columns +``` + +UI: + +```text +My Searches +Team Searches +``` + +--- + +# 107. Query Preset + +Plugin 可以提供: + +```text +preset +``` + +例如 SEO: + +```text +High Value Websites +Broken Backlinks +Low DR Websites +Recently Scanned +``` + +这些都是: + +```text +Saved Query / Query Preset +``` + +而不是每个页面重新写 SQL。 + +--- + +# 108. Data Table + +DevOS UI 应提供: + +```text +Generic Resource Table +``` + +支持: + +```text +columns +filter +sort +pagination +search +selection +bulk actions +saved views +export +``` + +--- + +# 109. Generic Resource Detail + +Resource Detail 页面可以自动生成: + +```text +Overview +Fields +Relations +Activity +Events +Tasks +Executions +Artifacts +``` + +Plugin 可以扩展: + +```text +Custom Tabs +Widgets +Actions +``` + +--- + +# 110. Bulk Operations + +大量操作: + +```text +Select 100 websites + ↓ +Bulk Action +``` + +不能: + +```text +HTTP request + ↓ +for each + ↓ +execute synchronously +``` + +必须: + +```text +Bulk Action + ↓ +Task + ↓ +Jobs +``` + +--- + +# 111. Bulk Job Expansion + +例如: + +```text +100 websites +``` + +创建: + +```text +1 Task ++ +100 Jobs +``` + +而不是: + +```text +100 Tasks +``` + +符合: + +```text +09_TASK_JOB_QUEUE_RUNTIME.md +``` + +--- + +# 112. Data Change Events + +Resource 数据发生变化: + +```text +created +updated +deleted +restored +archived +``` + +事件: + +```text +core.resource.created +core.resource.updated +core.resource.deleted +``` + +Plugin 可以订阅。 + +--- + +# 113. Event Payload + +Event 不应该发送完整 Resource: + +```text +巨大 Payload +``` + +默认: + +```ts +interface ResourceChangedEvent { + resource: string + + resourceId: string + + operation: 'created' | 'updated' | 'deleted' + + version: number + + changedFields?: string[] + + actorId: string + + timestamp: Date +} +``` + +Consumer 如果需要: + +```text +Query Resource +``` + +重新读取。 + +--- + +# 114. Search Index Event + +```text +Resource Updated + ↓ +Outbox + ↓ +Event + ↓ +Index Worker + ↓ +Search Index +``` + +这样: + +```text +Database +``` + +始终是: + +```text +Source of Truth +``` + +--- + +# 115. Reindex Safety + +Reindex 必须支持: + +```text +checkpoint +resume +retry +pause +cancel +``` + +因此: + +```text +Task +``` + +必须保存: + +```text +cursor +processedCount +failedCount +``` + +--- + +# 116. Search Provider Failure + +如果: + +```text +OpenSearch +``` + +挂了: + +业务数据: + +```text +仍然正常 +``` + +Search: + +```text +degraded +``` + +可以: + +```text +fallback PostgreSQL search +``` + +如果配置允许。 + +--- + +# 117. Search Fallback + +```ts +interface SearchPolicy { + primary: string + + fallback?: string[] + + failMode: + | 'fail' + | 'fallback' +} +``` + +--- + +# 118. Data Provider + +Data Runtime 也应该抽象: + +```ts +interface DataProvider { + query(...) + transaction(...) + health(...) +} +``` + +默认: + +```text +PostgreSQL +``` + +未来: + +```text +MySQL +SQLite +External API +``` + +但 DevOS Core 推荐: + +```text +PostgreSQL first +``` + +--- + +# 119. External Resource + +不是所有 Resource 都必须存在数据库。 + +例如: + +```text +GitHub Repository +Cloudflare Zone +AWS Server +``` + +可以: + +```text +External Resource Provider +``` + +```ts +interface ExternalResourceProvider { + get(id: string): Promise + + list(query: QueryInput): Promise> +} +``` + +--- + +# 120. External Resource Cache + +外部 Resource: + +```text +GitHub Repository +``` + +可以缓存: + +```text +Database ++ +Cache +``` + +但: + +```text +External API +``` + +仍然是真实来源。 + +--- + +# 121. Sync Runtime + +外部 Resource 同步: + +```text +External API + ↓ +Sync Task + ↓ +Job + ↓ +Worker + ↓ +Resource + ↓ +Database + ↓ +Index +``` + +--- + +# 122. Sync Cursor + +支持: + +```text +cursor +etag +updatedAt +lastSyncAt +``` + +减少: + +```text +API calls +``` + +--- + +# 123. Rate Limit + +Data Provider 必须支持: + +```text +rate limit +retry +backoff +concurrency +``` + +特别是: + +```text +GitHub +Cloudflare +AWS +External APIs +``` + +--- + +# 124. Provider Resource Boundary + +Provider 不应该: + +```text +直接修改核心数据库 +``` + +应该: + +```text +Provider + ↓ +External Data + ↓ +Action + ↓ +Resource Repository +``` + +--- + +# 125. Search Embedding Provider + +Embedding 也作为: + +```text +Provider +``` + +例如: + +```text +embedding.openai +embedding.local +``` + +接口: + +```ts +interface EmbeddingProvider { + embed( + input: string + ): Promise + + embedBatch( + inputs: string[] + ): Promise + + dimensions(): number +} +``` + +--- + +# 126. Embedding Task + +大量数据 embedding: + +```text +Resource + ↓ +Index Task + ↓ +Batch Jobs + ↓ +Embedding Provider + ↓ +Vector Index +``` + +不能: + +```text +API request + ↓ +10000 embeddings +``` + +--- + +# 127. Token Budget + +Embedding / Search / LLM 查询也要计入: + +```text +Agent Budget +``` + +尤其: + +```text +embedding calls +external search calls +``` + +--- + +# 128. Search Budget + +Agent Search: + +```ts +interface SearchBudget { + maxQueries: number + + maxResults: number + + maxExternalCalls: number + + maxEstimatedCost?: number +} +``` + +--- + +# 129. Data Access Audit + +敏感 Resource Query: + +```text +User + ↓ +Query + ↓ +Audit +``` + +尤其: + +```text +User +Credential +Secret Metadata +Billing +Audit +Organization +``` + +--- + +# 130. Query Audit Policy + +Resource Schema 可以定义: + +```ts +audit?: { + read: boolean + + sensitiveRead: boolean + + export: boolean +} +``` + +--- + +# 131. Data Access Observability + +Metrics: + +```text +devos_query_total +devos_query_duration +devos_query_errors +devos_query_rows +devos_query_cache_hit +devos_search_total +devos_search_duration +devos_search_errors +devos_index_documents +devos_index_failures +``` + +--- + +# 132. Database Index Definition + +Resource Schema: + +```ts +interface IndexDefinition { + name: string + + fields: string[] + + unique?: boolean + + type?: + | 'btree' + | 'gin' + | 'gist' + | 'hash' + + where?: string +} +``` + +禁止 Plugin 在 Runtime: + +```text +CREATE INDEX +``` + +Schema Migration 才能修改数据库结构。 + +--- + +# 133. Migration Integration + +结合: + +```text +12_MIGRATION_VERSIONING_COMPATIBILITY.md +``` + +新增 Index: + +```text +Migration +``` + +删除 Index: + +```text +Migration +``` + +修改 Schema: + +```text +Migration +``` + +--- + +# 134. Schema Registry + +统一: + +```ts +interface SchemaRegistry { + register( + schema: ResourceSchema + ): void + + get( + resource: string, + version?: string + ): ResourceSchema + + list(): ResourceSchema[] + + validate( + resource: string, + data: unknown + ): ValidationResult +} +``` + +--- + +# 135. Schema Versioning + +Resource: + +```text +seo.website +``` + +Schema: + +```text +1.0 +1.1 +2.0 +``` + +结合: + +```text +12_MIGRATION_VERSIONING_COMPATIBILITY.md +``` + +数据迁移必须可追踪。 + +--- + +# 136. API Schema + +Resource Schema 应自动生成: + +```text +REST schema +OpenAPI schema +MCP schema +Agent tool schema +UI schema +TypeScript types +``` + +减少重复定义。 + +--- + +# 137. Single Source of Truth + +最终: + +```text +Resource Schema + │ + ┌─────┼─────┬─────┬─────┐ + │ │ │ │ │ +API UI MCP Agent DB +``` + +不要: + +```text +API schema +UI schema +MCP schema +Agent schema +DB schema +``` + +分别维护。 + +--- + +# 138. Query Schema Generation + +Resource Schema 自动生成: + +```text +Filter Fields +Sort Fields +Search Fields +Selectable Fields +Relation Fields +``` + +这样 Generic UI 可以直接使用。 + +--- + +# 139. Plugin Example + +Plugin: + +```text +seo +``` + +注册: + +```text +seo.website +seo.article +seo.backlink +``` + +每个 Resource: + +```text +Schema +Actions +Relations +Search +Indexes +UI metadata +``` + +安装后自动进入: + +```text +Resource Registry +Query Runtime +Search Runtime +Action Runtime +UI +Agent Capability Registry +``` + +--- + +# 140. SEO Example + +用户: + +```text +找出 DR > 50 +且最近 30 天没有发布文章的网站 +``` + +Agent: + +```text +Goal + ↓ +Capability Discovery + ↓ +seo.website.search + ↓ +Query + ↓ +Filter +``` + +最终: + +```text +DR > 50 +AND +lastArticleAt < now - 30d +``` + +而不是: + +```text +Agent + ↓ +读取所有网站 + ↓ +自己计算 +``` + +--- + +# 141. Natural Language Query + +未来支持: + +```text +“找出过去一周失败最多的 Worker” +``` + +转换: + +```text +Natural Language + ↓ +Query Planner + ↓ +Resource + ↓ +Fields + ↓ +Filters + ↓ +Aggregates + ↓ +Query Runtime +``` + +但是: + +```text +LLM generated query +``` + +必须经过: + +```text +Schema Validation +Permission +Scope +Cost Check +``` + +--- + +# 142. Query Planner + +可以定义: + +```ts +interface QueryPlan { + resource: string + + query: QueryInput + + explanation?: string + + estimatedCost?: QueryCost +} +``` + +Agent 生成: + +```text +QueryPlan +``` + +Runtime 验证后执行。 + +--- + +# 143. Query Planner Safety + +LLM 不能生成: + +```sql +DROP TABLE +``` + +也不能: + +```text +raw SQL +``` + +只能生成: + +```text +QueryInput +``` + +--- + +# 144. Search Planner + +同样: + +```ts +interface SearchPlan { + resource: string + + input: SearchInput + + estimatedCost?: number +} +``` + +--- + +# 145. Query Result + +统一: + +```ts +interface QueryResult { + items: T[] + + pagination?: PaginationResult + + total?: number + + aggregates?: Record + + metadata?: Record +} +``` + +--- + +# 146. Search Result + +```ts +interface SearchResult { + items: SearchItem[] + + nextCursor?: string + + total?: number + + tookMs: number +} +``` + +```ts +interface SearchItem { + item: T + + score?: number + + highlights?: Record +} +``` + +--- + +# 147. Query Errors + +统一错误: + +```text +invalid_filter +invalid_field +invalid_sort +forbidden_field +forbidden_resource +scope_violation +query_timeout +query_too_expensive +provider_unavailable +``` + +--- + +# 148. Search Errors + +```text +invalid_query +unsupported_mode +index_unavailable +provider_unavailable +search_timeout +search_budget_exceeded +``` + +--- + +# 149. CLI + +增加: + +```bash +devos data resources + +devos data schema seo.website + +devos data query seo.website + +devos data count seo.website + +devos data export seo.website + +devos search "AI SEO" + +devos search "AI SEO" --resource seo.website + +devos index list + +devos index rebuild seo.website + +devos index health +``` + +--- + +# 150. UI + +DevOS 应提供: + +```text +Resource Explorer +``` + +例如: + +```text +Resources +├── Core +│ ├── Users +│ ├── Organizations +│ ├── Tasks +│ ├── Jobs +│ └── Executions +│ +└── Plugins + └── SEO + ├── Websites + ├── Articles + └── Backlinks +``` + +--- + +# 151. Resource Explorer + +统一页面: + +```text +List + ├── Search + ├── Filter + ├── Sort + ├── Columns + ├── Saved Views + ├── Bulk Actions + └── Export +``` + +--- + +# 152. Resource Detail + +统一: + +```text +Overview +Relations +Activity +Events +Tasks +Executions +Artifacts +``` + +Plugin 可以增加: + +```text +SEO Analysis +Backlinks +AI Recommendations +``` + +--- + +# 153. Search UI + +全局: + +```text +⌘K / Ctrl+K +``` + +输入: + +```text +AI SEO +``` + +返回: + +```text +Websites +Articles +Tasks +Plugins +Skills +Actions +``` + +按照: + +```text +relevance +``` + +排序。 + +--- + +# 154. Saved View + +用户可以: + +```text +保存当前: +filter +sort +columns +search +``` + +例如: + +```text +Failed Tasks +High DR Websites +Production Deployments +``` + +--- + +# 155. Data Table Performance + +必须支持: + +```text +server-side pagination +server-side sorting +server-side filtering +virtualization +``` + +禁止: + +```text +GET 100000 records + ↓ +browser filter +``` + +--- + +# 156. Bulk UI + +Bulk Action: + +```text +Select + ↓ +Action + ↓ +Confirmation + ↓ +Task created + ↓ +Task Detail +``` + +不能长时间阻塞页面。 + +--- + +# 157. Import + +未来提供: + +```text +core.import +``` + +支持: + +```text +CSV +JSON +JSONL +Excel +``` + +流程: + +```text +Upload Artifact + ↓ +Import Task + ↓ +Validate + ↓ +Preview + ↓ +Confirm + ↓ +Batch Jobs + ↓ +Actions +``` + +--- + +# 158. Import Validation + +必须先: + +```text +dry-run +``` + +显示: + +```text +1000 rows +980 valid +15 warnings +5 errors +``` + +用户确认后: + +```text +execute +``` + +--- + +# 159. Import Security + +Import 必须: + +```text +schema validation +field permission +scope validation +file size limit +row limit +rate limit +``` + +--- + +# 160. Data Runtime Package + +目录: + +```text +packages/data/ +├── data-runtime.ts +├── data-context.ts +├── repository.ts +├── data-provider.ts +├── query/ +│ ├── query-runtime.ts +│ ├── query-schema.ts +│ ├── query-validator.ts +│ ├── query-planner.ts +│ ├── query-cost.ts +│ └── query-compiler.ts +├── filter/ +├── pagination/ +├── relation/ +├── aggregate/ +├── cache/ +└── index.ts +``` + +--- + +# 161. Search Package + +```text +packages/search/ +├── search-runtime.ts +├── search-provider.ts +├── search-schema.ts +├── search-planner.ts +├── ranking.ts +├── index-runtime.ts +├── index-registry.ts +├── embedding/ +├── providers/ +└── index.ts +``` + +--- + +# 162. Schema Package + +```text +packages/schema/ +├── schema-registry.ts +├── resource-schema.ts +├── field-definition.ts +├── relation-definition.ts +├── index-definition.ts +├── validation.ts +└── index.ts +``` + +--- + +# 163. Cache Package + +```text +packages/cache/ +├── cache-runtime.ts +├── cache-provider.ts +├── cache-key.ts +├── invalidation.ts +└── index.ts +``` + +--- + +# 164. Export Package + +```text +packages/export/ +├── export-service.ts +├── csv.ts +├── json.ts +├── jsonl.ts +├── excel.ts +└── index.ts +``` + +--- + +# 165. Import Package + +```text +packages/import/ +├── import-service.ts +├── parser.ts +├── validator.ts +├── preview.ts +├── importer.ts +└── index.ts +``` + +--- + +# 166. Database + +第一阶段: + +```text +PostgreSQL +``` + +推荐: + +```text +PostgreSQL ++ +pgvector +``` + +用于: + +```text +transactional data +full text +JSON +vector +``` + +减少: + +```text +Elasticsearch +RedisSearch +Vector DB +``` + +等额外基础设施。 + +--- + +# 167. When To Add Search Engine + +只有出现: + +```text +数据规模 +搜索复杂度 +性能要求 +``` + +明确超过 PostgreSQL 能力时,再接: + +```text +OpenSearch +Elasticsearch +Meilisearch +``` + +Search Runtime 必须让切换 Provider 不影响上层。 + +--- + +# 168. Database Is Source of Truth + +绝对原则: + +```text +PostgreSQL + = +Source of Truth + +Search Index + = +Derived State + +Cache + = +Derived State +``` + +--- + +# 169. Data Runtime Integration + +完整链: + +```text +Resource + ↓ +Schema + ↓ +Permission + ↓ +Scope + ↓ +Query Runtime + ↓ +Repository + ↓ +Data Provider + ↓ +PostgreSQL +``` + +Search: + +```text +Resource + ↓ +Schema + ↓ +Permission + ↓ +Scope + ↓ +Search Runtime + ↓ +Search Provider + ↓ +Index +``` + +--- + +# 170. Action Integration + +写入: + +```text +Action + ↓ +Action Runtime + ↓ +Domain Logic + ↓ +Repository + ↓ +Transaction + ↓ +Database + ↓ +Outbox + ↓ +Event +``` + +--- + +# 171. Index Integration + +```text +Event + ↓ +Index Job + ↓ +Worker + ↓ +Search Runtime + ↓ +Search Provider +``` + +--- + +# 172. Agent Integration + +Agent: + +```text +Goal + ↓ +Search / Query Capability + ↓ +QueryPlan / SearchPlan + ↓ +Runtime Validation + ↓ +Execution +``` + +Agent 不允许: + +```text +Database Access +``` + +--- + +# 173. MCP Integration + +MCP: + +```text +MCP + ↓ +Capability + ↓ +Search / Query Action + ↓ +Data Runtime +``` + +禁止: + +```text +MCP → PostgreSQL +``` + +--- + +# 174. Plugin Integration + +Plugin 只需要声明: + +```text +Resource Schema +Actions +Search Definition +Indexes +Relations +``` + +DevOS 自动获得: + +```text +Query +Search +Generic UI +Global Search +Agent Capability +MCP Exposure +``` + +--- + +# 175. Acceptance Criteria + +## Data + +```text +[ ] Data Runtime +[ ] Repository +[ ] Data Provider +[ ] Query Runtime +[ ] Filter +[ ] Sort +[ ] Pagination +[ ] Relations +[ ] Aggregate +[ ] Scope +``` + +## Search + +```text +[ ] Search Runtime +[ ] Full Text +[ ] Semantic +[ ] Hybrid abstraction +[ ] Search Provider +[ ] Index Runtime +[ ] Incremental Index +[ ] Rebuild +[ ] Search Ranking +``` + +## Security + +```text +[ ] Field permission +[ ] Row scope +[ ] Query authorization +[ ] Search authorization +[ ] Export authorization +[ ] Sensitive field masking +``` + +## Performance + +```text +[ ] Query timeout +[ ] Query cost +[ ] Slow query detection +[ ] Cache +[ ] DataLoader +[ ] Batch +[ ] Cursor pagination +``` + +## Integration + +```text +[ ] Resource Registry +[ ] Action Runtime +[ ] Task Runtime +[ ] Event Runtime +[ ] Agent Runtime +[ ] MCP Runtime +[ ] Plugin Runtime +``` + +--- + +# 176. Integration Tests + +必须测试: + +```text +Resource + ↓ +Query + ↓ +Permission + ↓ +Scope + ↓ +Database +``` + +测试: + +```text +Org A cannot query Org B + +User cannot query forbidden field + +Invalid filter rejected + +Invalid sort rejected + +Large query rejected + +Query timeout works + +Cursor pagination works + +Relations do not produce N+1 + +Aggregate respects permission +``` + +--- + +# 177. Search Tests + +测试: + +```text +full text search +semantic search +hybrid search +ranking +filter +scope +permission +index rebuild +incremental index +index failure +index recovery +fallback +``` + +--- + +# 178. Agent Tests + +测试: + +```text +Agent uses Query for structured requirement + +Agent uses Search for semantic requirement + +Agent cannot query unauthorized Resource + +Agent cannot request forbidden fields + +Agent cannot generate raw SQL + +Agent respects search budget + +Agent respects query limits +``` + +--- + +# 179. MCP Tests + +测试: + +```text +MCP query +MCP search +MCP permission +MCP scope +MCP budget +MCP timeout +MCP cannot bypass Data Runtime +``` + +--- + +# 180. Plugin Tests + +安装 Plugin: + +```text +Plugin + ↓ +Resource Schema + ↓ +Registry + ↓ +Query + ↓ +Search + ↓ +Generic UI + ↓ +Agent Capability +``` + +必须全部自动生效。 + +--- + +# 181. Zcode Implementation Rules + +## Rule 1 + +任何业务数据读取: + +```text +必须经过 Data Runtime +``` + +--- + +## Rule 2 + +任何业务数据写入: + +```text +必须经过 Action Runtime +``` + +--- + +## Rule 3 + +禁止: + +```text +UI → Prisma +Plugin → Prisma +Agent → Prisma +MCP → Prisma +``` + +--- + +## Rule 4 + +禁止暴露: + +```text +raw SQL +``` + +给: + +```text +Agent +MCP +Plugin public API +REST client +``` + +--- + +## Rule 5 + +所有 Query 必须执行: + +```text +Schema Validation +Permission +Scope +Cost Check +Timeout +``` + +--- + +## Rule 6 + +所有 Search 必须执行: + +```text +Permission +Scope +Budget +``` + +--- + +## Rule 7 + +Database 是: + +```text +Source of Truth +``` + +Search Index 和 Cache 都是: + +```text +Derived State +``` + +--- + +## Rule 8 + +Index 更新必须通过: + +```text +Event ++ +Task/Job ++ +Worker +``` + +支持: + +```text +retry +resume +rebuild +``` + +--- + +## Rule 9 + +大数据量操作必须: + +```text +Task ++ +Job ++ +Cursor +``` + +不能同步读取全部数据。 + +--- + +## Rule 10 + +Resource Schema 必须成为: + +```text +Single Source of Truth +``` + +驱动: + +```text +Database +API +UI +MCP +Agent +Search +``` + +--- + +# 182. Golden Rule + +DevOS 数据体系必须遵循: + +```text +Resource + ↓ +Schema + ↓ +Permission + ↓ +Scope + ↓ +Query / Search + ↓ +Data Runtime + ↓ +Provider + ↓ +Database / Index +``` + +写入: + +```text +Action + ↓ +Action Runtime + ↓ +Data Runtime + ↓ +Database + ↓ +Outbox + ↓ +Event + ↓ +Index / Cache / Plugin / Agent +``` + +最终形成: + +```text + Resource + │ + Schema + │ + ┌──────────┴──────────┐ + │ │ + Action Query + │ │ + Action Runtime Query Runtime + │ │ + │ ┌─────┴─────┐ + │ │ │ + │ Repository Search + │ │ │ + │ │ Search Runtime + │ │ │ + └───────┬───────┘ Search Index + │ + Database + │ + Outbox + │ + Event + │ + ┌──────────┼──────────┐ + │ │ │ + Cache Index Plugin + │ │ │ + └──────────┼──────────┘ + │ + Agent +``` + +--- + +# 183. Final Principle + +DevOS 不应该让每一个 Plugin 自己实现: + +```text +Pagination +Filter +Search +Permission Filter +Scope +Export +Import +Cache +Index +Relation +Query Builder +Data Table +``` + +这些应该全部成为: + +```text +DevOS Data Platform +``` + +于是一个新的业务 Plugin 只需要定义: + +```text +Resource Schema ++ +Actions ++ +Relations ++ +Search Definition +``` + +DevOS 自动提供: + +```text +Database +Query +Search +Index +Permission +Scope +Pagination +Generic UI +Global Search +Agent Capability +MCP Capability +Export +Import +Cache +Audit +Observability +``` + +这才是真正意义上的: + +```text +Reusable Development OS +``` + +而不是: + +```text +一个拥有很多功能的 Backend Template +``` diff --git a/Docs/DevOS-Platform-v2/15_FILE_ARTIFACT_STORAGE_RUNTIME.md b/Docs/DevOS-Platform-v2/15_FILE_ARTIFACT_STORAGE_RUNTIME.md new file mode 100644 index 0000000..2e078d3 --- /dev/null +++ b/Docs/DevOS-Platform-v2/15_FILE_ARTIFACT_STORAGE_RUNTIME.md @@ -0,0 +1,4450 @@ +# DevOS File / Artifact / Storage Runtime + +> Document: 15 +> Status: Required +> Audience: Zcode / DevOS Core Team +> Depends On: +> - 03_RESOURCE_ACTION_MODEL.md +> - 06_MCP_SKILL_AGENT_RUNTIME.md +> - 09_TASK_JOB_QUEUE_RUNTIME.md +> - 12_MIGRATION_VERSIONING_COMPATIBILITY.md +> - 13_DEPLOYMENT_ENVIRONMENT_CONFIG_RUNTIME.md +> - 14_DATA_QUERY_SEARCH_INDEX_RUNTIME.md + +--- + +# 1. Goals + +DevOS 中会出现大量文件: + +- 用户上传文件 +- 图片 +- 视频 +- PDF +- CSV +- Excel +- Markdown +- AI 生成内容 +- SEO 文章 +- Agent 输出 +- Task 输出 +- Job 日志 +- Deployment 包 +- Build 产物 +- Backup +- Import 文件 +- Export 文件 +- MCP 下载内容 +- Plugin 资源 + +不能让每个 Plugin 自己处理: + +```text +上传 +下载 +对象存储 +文件权限 +文件版本 +临时 URL +文件预览 +Hash +病毒扫描 +生命周期 +删除 +备份 +```` + +必须统一成为: + +```text +DevOS Storage Runtime +``` + +--- + +# 2. Core Principle + +DevOS 必须区分: + +```text +File +Blob +Artifact +Attachment +Storage Object +``` + +--- + +# 3. File + +File 表示: + +> 用户或系统可识别的文件对象。 + +例如: + +```text +logo.png +article.md +report.pdf +backup.zip +``` + +File 是: + +```text +Metadata ++ +Storage Reference +``` + +而不是直接保存文件二进制。 + +--- + +# 4. Blob + +Blob 表示: + +> 实际二进制数据。 + +例如: + +```text +image bytes +zip bytes +pdf bytes +``` + +Blob 可以存在: + +```text +Local Disk +S3 +MinIO +Cloudflare R2 +Azure Blob +GCS +``` + +--- + +# 5. Artifact + +Artifact 表示: + +> 某个 Task / Job / Action / Build / Deployment 产生的可追踪输出。 + +例如: + +```text +Task + └── Artifact + ├── report.pdf + ├── data.csv + └── result.json +``` + +Artifact 比 File 更强调: + +```text +来源 +版本 +执行过程 +生命周期 +``` + +--- + +# 6. Attachment + +Attachment 表示: + +> 一个 Resource / Task / Message / Agent Run 等对象关联的 File。 + +例如: + +```text +Task + └── attachments + ├── input.csv + └── output.xlsx +``` + +--- + +# 7. Storage Object + +Storage Object 是底层存储抽象: + +```text +bucket +key +size +etag +contentType +checksum +``` + +--- + +# 8. Architecture + +```text + DevOS File System + │ + ┌────────────┴────────────┐ + │ │ + File Artifact + │ │ + └────────────┬────────────┘ + │ + Storage Runtime + │ + Storage Provider + │ + ┌────────────────┼────────────────┐ + │ │ │ + Local S3 R2 + Disk Compatible +``` + +--- + +# 9. Storage Runtime + +统一接口: + +```ts +export interface StorageRuntime { + put( + input: PutObjectInput, + context: StorageContext + ): Promise + + get( + input: GetObjectInput, + context: StorageContext + ): Promise + + delete( + input: DeleteObjectInput, + context: StorageContext + ): Promise + + exists( + input: ExistsObjectInput, + context: StorageContext + ): Promise + + stat( + input: StatObjectInput, + context: StorageContext + ): Promise +} +``` + +--- + +# 10. Storage Provider + +```ts +export interface StorageProvider { + name: string + + put( + input: PutObjectInput + ): Promise + + get( + input: GetObjectInput + ): Promise + + delete( + input: DeleteObjectInput + ): Promise + + exists( + input: ExistsObjectInput + ): Promise + + stat( + input: StatObjectInput + ): Promise + + createPresignedUrl?( + input: PresignedUrlInput + ): Promise + + health(): Promise +} +``` + +--- + +# 11. StorageContext + +所有 Storage 操作必须有: + +```ts +export interface StorageContext { + requestId: string + + actor: Actor + + organizationId?: string + + projectId?: string + + environmentId?: string + + permissions: string[] + + metadata?: Record +} +``` + +不能: + +```text +Plugin + ↓ +Storage Provider +``` + +直接访问。 + +必须: + +```text +Plugin + ↓ +Storage Runtime + ↓ +Permission + ↓ +Storage Provider +``` + +--- + +# 12. File Resource + +File 是 DevOS Resource: + +```text +core.file +``` + +建议字段: + +```ts +export interface FileRecord { + id: string + + name: string + + originalName?: string + + mimeType: string + + extension?: string + + size: number + + checksum?: string + + checksumAlgorithm?: string + + storageProvider: string + + storageBucket?: string + + storageKey: string + + status: FileStatus + + ownerId?: string + + organizationId?: string + + projectId?: string + + createdAt: Date + + updatedAt: Date + + deletedAt?: Date +} +``` + +--- + +# 13. File Status + +```text +pending +uploading +processing +ready +quarantined +failed +deleting +deleted +``` + +--- + +# 14. File Lifecycle + +```text +Upload + ↓ +Pending + ↓ +Uploading + ↓ +Processing + ↓ +Security Scan + ↓ +Ready +``` + +失败: + +```text +Processing + ↓ +Failed +``` + +危险: + +```text +Processing + ↓ +Quarantined +``` + +--- + +# 15. Storage Key + +禁止直接使用: + +```text +uploads/logo.png +``` + +避免: + +```text +filename collision +organization collision +path traversal +``` + +推荐: + +```text +{organizationId}/{resource}/{year}/{month}/{uuid} +``` + +例如: + +```text +org_123/ +core.file/ +2026/ +09/ +file_abc123 +``` + +--- + +# 16. Never Trust Filename + +用户上传: + +```text +../../etc/passwd +``` + +必须安全转换。 + +Storage Key 绝不能直接使用: + +```text +originalName +``` + +--- + +# 17. Original Filename + +Original filename 只作为: + +```text +metadata +``` + +保存: + +```text +originalName +``` + +真正 Storage Key: + +```text +UUID +``` + +--- + +# 18. MIME Type + +客户端提供的: + +```text +Content-Type +``` + +不能完全信任。 + +系统应: + +```text +extension check ++ +content sniffing +``` + +必要时验证: + +```text +magic bytes +``` + +--- + +# 19. File Validation + +上传时必须验证: + +```text +mimeType +extension +size +checksum +filename +``` + +可选: + +```text +image dimensions +video duration +PDF validity +archive contents +``` + +--- + +# 20. Upload Policy + +每个 Resource / Plugin 可以定义: + +```ts +export interface UploadPolicy { + maxSizeBytes: number + + allowedMimeTypes?: string[] + + allowedExtensions?: string[] + + maxFiles?: number + + requireScan?: boolean + + requireChecksum?: boolean +} +``` + +--- + +# 21. Default Limits + +必须提供全局: + +```text +storage.maxFileSize +storage.maxTotalUploadSize +storage.maxFilesPerRequest +``` + +不能无限制上传。 + +--- + +# 22. Chunked Upload + +大文件必须支持: + +```text +Multipart Upload +``` + +流程: + +```text +Create Upload + ↓ +Upload Parts + ↓ +Complete Upload + ↓ +Verify + ↓ +Process +``` + +--- + +# 23. Upload Session + +Resource: + +```text +core.uploadSession +``` + +```ts +export interface UploadSession { + id: string + + filename: string + + size: number + + mimeType: string + + totalParts?: number + + uploadedParts: number + + status: + | 'created' + | 'uploading' + | 'completed' + | 'failed' + | 'cancelled' + + expiresAt: Date +} +``` + +--- + +# 24. Resumable Upload + +如果网络断开: + +```text +Upload Part 1 +Upload Part 2 +Upload Part 3 +↓ +Network Failure +↓ +Resume +↓ +Upload Part 4 +``` + +不能重新上传整个文件。 + +--- + +# 25. Presigned URL + +大文件: + +```text +Browser + ↓ +Presigned URL + ↓ +Object Storage +``` + +不要: + +```text +Browser + ↓ +DevOS Backend + ↓ +Object Storage +``` + +把所有大文件流量经过 API。 + +--- + +# 26. Presigned URL Security + +URL 必须: + +```text +short-lived +scoped +permission checked +``` + +例如: + +```text +expires = 5 minutes +``` + +不能生成: + +```text +permanent public URL +``` + +除非明确配置。 + +--- + +# 27. Download Action + +统一: + +```text +core.file.download +``` + +执行: + +```text +Permission + ↓ +Scope + ↓ +File status + ↓ +Generate URL +``` + +--- + +# 28. Preview Action + +```text +core.file.preview +``` + +支持: + +```text +image +PDF +text +JSON +CSV +Markdown +video +audio +``` + +具体能力由 Preview Provider 决定。 + +--- + +# 29. Preview Provider + +```ts +export interface PreviewProvider { + supports( + mimeType: string + ): boolean + + preview( + file: FileRecord + ): Promise +} +``` + +--- + +# 30. Preview Result + +```ts +export interface PreviewResult { + type: + | 'inline' + | 'redirect' + | 'generated' + + mimeType?: string + + url?: string + + content?: string + + pages?: number + + metadata?: Record +} +``` + +--- + +# 31. Image Metadata + +图片可提取: + +```text +width +height +format +orientation +``` + +可选: + +```text +EXIF +``` + +但: + +```text +GPS +``` + +等敏感元数据默认应该: + +```text +not exposed +``` + +--- + +# 32. File Processing + +上传后: + +```text +File + ↓ +Processing Task + ↓ +Jobs +``` + +处理: + +```text +Virus Scan +Metadata +Thumbnail +Text Extraction +OCR +Embedding +Indexing +``` + +--- + +# 33. File Processing Pipeline + +```text +Upload + ↓ +Verify + ↓ +Scan + ↓ +Metadata + ↓ +Preview + ↓ +Text Extraction + ↓ +Embedding + ↓ +Search Index +``` + +不是所有文件都需要执行全部步骤。 + +--- + +# 34. Processing Capability + +```ts +export interface FileProcessor { + id: string + + supports( + file: FileRecord + ): boolean + + process( + file: FileRecord, + context: ProcessingContext + ): Promise +} +``` + +--- + +# 35. Processor Types + +```text +security.scan +metadata.extract +thumbnail.generate +text.extract +ocr +embedding.generate +search.index +``` + +--- + +# 36. Virus Scanning + +如果启用: + +```text +Upload + ↓ +Quarantine + ↓ +Security Scanner + ↓ +Clean / Infected +``` + +Infected: + +```text +quarantined +``` + +禁止: + +```text +download +preview +agent access +``` + +直到人工/系统处理。 + +--- + +# 37. Security Scanner Provider + +```ts +export interface SecurityScanner { + scan( + input: ScanInput + ): Promise +} +``` + +可接: + +```text +ClamAV +External Security Service +``` + +但 Storage Runtime 不应该绑定具体实现。 + +--- + +# 38. Text Extraction + +支持: + +```text +PDF +DOCX +TXT +Markdown +HTML +CSV +JSON +``` + +输出: + +```text +ExtractedText +``` + +--- + +# 39. Extracted Text + +Resource: + +```text +core.fileText +``` + +```ts +export interface FileText { + fileId: string + + text: string + + language?: string + + extractedAt: Date + + extractor: string + + version: string +} +``` + +--- + +# 40. File Search + +结合: + +```text +14_DATA_QUERY_SEARCH_INDEX_RUNTIME.md +``` + +文件内容可以进入: + +```text +Search Runtime +``` + +例如: + +```text +搜索: +“Cloudflare production deployment” +``` + +可以搜索: + +```text +PDF +Markdown +DOCX +Task Output +Reports +``` + +--- + +# 41. File Embedding + +支持: + +```text +File + ↓ +Text Extraction + ↓ +Chunk + ↓ +Embedding + ↓ +Vector Index +``` + +用于: + +```text +RAG +Agent +Knowledge Base +Semantic Search +``` + +--- + +# 42. File Chunk + +```ts +export interface FileChunk { + id: string + + fileId: string + + index: number + + text: string + + startOffset?: number + + endOffset?: number + + embedding?: number[] + + metadata?: Record +} +``` + +--- + +# 43. Chunk Strategy + +不要固定一种 Chunk。 + +支持: + +```text +token based +character based +paragraph based +heading based +semantic +``` + +默认优先: + +```text +paragraph / heading aware +``` + +--- + +# 44. RAG Integration + +最终: + +```text +User Question + ↓ +Search Runtime + ↓ +File Search + ↓ +Vector Search + ↓ +Top K Chunks + ↓ +Agent Context +``` + +而不是: + +```text +Agent + ↓ +读取整个 PDF +``` + +--- + +# 45. Artifact Resource + +```text +core.artifact +``` + +```ts +export interface Artifact { + id: string + + name: string + + type: string + + fileId: string + + sourceType: + | 'task' + | 'job' + | 'execution' + | 'action' + | 'agent' + | 'build' + | 'deployment' + | 'plugin' + | 'system' + + sourceId: string + + version: number + + metadata?: Record + + createdAt: Date +} +``` + +--- + +# 46. Artifact Examples + +Task: + +```text +Generate SEO Report +``` + +Artifacts: + +```text +report.pdf +websites.csv +summary.json +``` + +--- + +# 47. Artifact Version + +如果 Task 重新执行: + +```text +Artifact v1 +Artifact v2 +Artifact v3 +``` + +而不是: + +```text +overwrite +``` + +默认保留版本。 + +--- + +# 48. Artifact Versioning + +```ts +export interface ArtifactVersion { + id: string + + artifactId: string + + version: number + + fileId: string + + executionId?: string + + checksum: string + + createdAt: Date +} +``` + +--- + +# 49. Reproducibility + +Artifact 必须关联: + +```text +Task +Job +Execution +Action Version +Plugin Version +Runtime Version +``` + +结合: + +```text +12_MIGRATION_VERSIONING_COMPATIBILITY.md +``` + +这样: + +```text +Artifact +``` + +可以回答: + +```text +这个文件是谁生成的? +用什么版本生成? +什么时候生成? +为什么生成? +``` + +--- + +# 50. Artifact Provenance + +```ts +export interface ArtifactProvenance { + sourceType: string + + sourceId: string + + executionId?: string + + actorId: string + + runtimeVersion: string + + pluginVersions?: Record + + actionVersion?: string + + createdAt: Date +} +``` + +--- + +# 51. Artifact Lineage + +例如: + +```text +Input CSV + ↓ +Import Task + ↓ +Normalized Data + ↓ +Analysis Task + ↓ +Report PDF +``` + +系统应保存: + +```text +Artifact A + ↓ +Task + ↓ +Artifact B +``` + +--- + +# 52. Artifact Relation + +```ts +export interface ArtifactRelation { + sourceArtifactId: string + + targetArtifactId: string + + relation: + | 'derived_from' + | 'generated_from' + | 'converted_from' + | 'aggregated_from' +} +``` + +--- + +# 53. Agent Artifact + +Agent 产生文件: + +```text +Agent + ↓ +Task + ↓ +Action + ↓ +Artifact +``` + +Agent 不直接: + +```text +write /tmp/output.pdf +``` + +然后告诉系统: + +```text +done +``` + +必须注册: + +```text +Artifact +``` + +--- + +# 54. Agent File Access + +Agent 只能访问: + +```text +authorized File +``` + +必须经过: + +```text +File Capability +``` + +--- + +# 55. Agent File Capabilities + +```text +core.file.list +core.file.get +core.file.search +core.file.preview +core.file.download +core.artifact.list +core.artifact.get +``` + +写: + +```text +core.file.create +core.artifact.create +``` + +必须仍然经过: + +```text +Action Runtime +``` + +--- + +# 56. MCP File Access + +MCP: + +```text +MCP + ↓ +Capability + ↓ +File Runtime +``` + +禁止: + +```text +MCP + ↓ +filesystem.readFile() +``` + +--- + +# 57. Local Filesystem + +DevOS 可以使用: + +```text +Local Storage Provider +``` + +但 Local Provider 只能访问: + +```text +configured storage root +``` + +例如: + +```text +/var/lib/devos/storage +``` + +禁止: + +```text +/ +``` + +作为 Storage Root。 + +--- + +# 58. Path Traversal + +必须防御: + +```text +../ +..\ +absolute paths +symlink escape +null bytes +``` + +Storage Key 必须规范化。 + +--- + +# 59. Storage Bucket + +Storage Provider 可以定义: + +```text +system +private +public +temporary +artifact +backup +``` + +例如: + +```text +devos-private +devos-artifacts +devos-temp +``` + +--- + +# 60. Bucket Policy + +```ts +export interface BucketPolicy { + name: string + + public: boolean + + maxObjectSize?: number + + retentionDays?: number + + encryptionRequired?: boolean +} +``` + +默认: + +```text +private +``` + +--- + +# 61. Encryption + +敏感文件支持: + +```text +Encryption At Rest +``` + +推荐依赖: + +```text +Object Storage Encryption +``` + +不要自己实现密码学。 + +--- + +# 62. Secret Files + +Secret 不应该使用普通: + +```text +core.file +``` + +保存。 + +例如: + +```text +API Key +Private Key +Cloud Credential +``` + +必须使用: + +```text +Secret Runtime +``` + +见: + +```text +13_DEPLOYMENT_ENVIRONMENT_CONFIG_RUNTIME.md +``` + +File Runtime 只保存: + +```text +reference +``` + +如果必须上传: + +```text +encrypt ++ +strict ACL ++ +no preview ++ +no indexing +``` + +--- + +# 63. Temporary Files + +Resource: + +```text +core.temporaryFile +``` + +或内部 Storage Namespace: + +```text +temporary +``` + +生命周期: + +```text +TTL +``` + +例如: + +```text +1 hour +24 hours +7 days +``` + +--- + +# 64. Temp File Cleanup + +Scheduler: + +```text +Scheduler + ↓ +Cleanup Task + ↓ +Job + ↓ +Worker + ↓ +Delete expired files +``` + +--- + +# 65. Artifact Retention + +不同 Artifact 类型不同策略: + +```text +Build Artifact +30 days + +Deployment Artifact +90 days + +Task Report +180 days + +User Upload +indefinite +``` + +具体由: + +```text +Retention Policy +``` + +决定。 + +--- + +# 66. Retention Policy + +```ts +export interface StorageRetentionPolicy { + resource: string + + retentionDays?: number + + archiveAfterDays?: number + + deleteAfterDays?: number + + preserveIfReferenced?: boolean +} +``` + +--- + +# 67. Reference Protection + +如果: + +```text +Artifact +``` + +仍被: + +```text +Task +Document +Deployment +``` + +引用: + +不能因为普通 TTL: + +```text +delete +``` + +除非: + +```text +force +``` + +且具备权限。 + +--- + +# 68. Garbage Collection + +Storage 中可能存在: + +```text +orphaned objects +``` + +例如: + +```text +Upload failed +DB transaction rollback +``` + +需要: + +```text +Storage GC +``` + +流程: + +```text +Scan Storage + ↓ +Compare DB + ↓ +Find Orphans + ↓ +Grace Period + ↓ +Delete +``` + +--- + +# 69. Garbage Collection Safety + +发现 orphan 后: + +```text +不要立即删除 +``` + +默认: + +```text +grace period = 24h +``` + +避免: + +```text +temporary inconsistency +``` + +--- + +# 70. Checksum + +默认: + +```text +SHA-256 +``` + +保存: + +```ts +checksum +checksumAlgorithm +``` + +用途: + +```text +duplicate detection +integrity +upload verification +artifact reproducibility +``` + +--- + +# 71. Deduplication + +相同: + +```text +checksum +``` + +可以复用 Storage Object。 + +但是: + +```text +File +``` + +仍然可以有不同 metadata。 + +即: + +```text +File A ─┐ + ├── Blob X +File B ─┘ +``` + +--- + +# 72. Deduplication Security + +Deduplication 不能导致: + +```text +Org A +``` + +推断: + +```text +Org B +``` + +存在相同文件。 + +因此: + +```text +cross-tenant dedup +``` + +默认关闭。 + +--- + +# 73. File Copy + +支持: + +```text +core.file.copy +``` + +逻辑: + +```text +File A + ↓ +New File + ↓ +same Blob +``` + +如果权限允许。 + +--- + +# 74. File Move + +逻辑上: + +```text +File + ↓ +change logical namespace +``` + +而不是: + +```text +download +upload +delete +``` + +--- + +# 75. File Rename + +```text +core.file.rename +``` + +只修改: + +```text +name +``` + +不需要重新上传 Blob。 + +--- + +# 76. File Delete + +删除流程: + +```text +Action + ↓ +Permission + ↓ +Reference Check + ↓ +Soft Delete + ↓ +Async Physical Delete +``` + +不要: + +```text +HTTP request + ↓ +delete object +``` + +同步阻塞。 + +--- + +# 77. Hard Delete + +必须是: + +```text +dangerous action +``` + +需要: + +```text +requiresApproval +``` + +的场景由 Resource Policy 决定。 + +--- + +# 78. File Events + +```text +core.file.created +core.file.updated +core.file.ready +core.file.quarantined +core.file.deleted +core.file.restored +``` + +Artifact: + +```text +core.artifact.created +core.artifact.version.created +``` + +--- + +# 79. Event Payload + +```ts +export interface FileEvent { + fileId: string + + organizationId?: string + + operation: string + + version: number + + actorId: string + + timestamp: Date +} +``` + +不要在 Event 中: + +```text +embed binary +``` + +--- + +# 80. Storage Metrics + +必须提供: + +```text +storage_bytes_total +storage_files_total +storage_upload_total +storage_download_total +storage_upload_bytes +storage_download_bytes +storage_errors_total +storage_processing_total +storage_quarantine_total +storage_gc_total +``` + +--- + +# 81. Storage Health + +```ts +export interface StorageHealth { + provider: string + + status: + | 'healthy' + | 'degraded' + | 'unavailable' + + latencyMs?: number + + availableBytes?: number + + error?: string +} +``` + +--- + +# 82. Storage Provider Registry + +```ts +export interface StorageProviderRegistry { + register( + provider: StorageProvider + ): void + + get( + name: string + ): StorageProvider + + list(): StorageProvider[] +} +``` + +--- + +# 83. Default Provider + +开发: + +```text +local +``` + +生产: + +```text +S3-compatible +``` + +例如: + +```text +AWS S3 +MinIO +Cloudflare R2 +``` + +但上层: + +```text +Storage Runtime +``` + +不依赖具体厂商。 + +--- + +# 84. Provider Selection + +可以按: + +```text +environment +organization +resource +file type +``` + +选择 Storage Provider。 + +例如: + +```text +production + → S3 + +development + → local +``` + +--- + +# 85. Storage Policy + +```ts +export interface StoragePolicy { + defaultProvider: string + + providerByEnvironment?: Record + + maxFileSize: number + + allowedProviders?: string[] + + publicAccess: boolean +} +``` + +--- + +# 86. Public Files + +如果允许 Public: + +```text +File + ↓ +Public Policy + ↓ +Public URL +``` + +必须明确: + +```text +public = true +``` + +默认: + +```text +false +``` + +--- + +# 87. CDN + +大文件 / Public Asset: + +```text +Browser + ↓ +CDN + ↓ +Object Storage +``` + +DevOS 只负责: + +```text +authorization +metadata +URL generation +``` + +--- + +# 88. Attachment API + +统一: + +```text +POST /api/files/upload +GET /api/files/:id +GET /api/files/:id/download +GET /api/files/:id/preview +DELETE /api/files/:id +``` + +--- + +# 89. Artifact API + +```text +GET /api/artifacts +GET /api/artifacts/:id +GET /api/artifacts/:id/versions +GET /api/artifacts/:id/download +``` + +--- + +# 90. Upload API + +推荐: + +```text +POST /api/uploads +POST /api/uploads/:id/parts +POST /api/uploads/:id/complete +POST /api/uploads/:id/cancel +``` + +大文件优先: + +```text +Presigned Upload +``` + +--- + +# 91. Upload Flow + +```text +Client + ↓ +Create Upload Session + ↓ +DevOS Authorization + ↓ +Presigned URL + ↓ +Object Storage + ↓ +Complete + ↓ +DevOS Verify + ↓ +Processing Task + ↓ +File Ready +``` + +--- + +# 92. UI Upload Component + +DevOS 提供: + +```text + +``` + +支持: + +```text +drag & drop +multiple +progress +pause +resume +cancel +retry +preview +validation +``` + +--- + +# 93. Artifact UI + +Task 页面: + +```text +Task + ├── Overview + ├── Jobs + ├── Logs + ├── Artifacts + │ ├── report.pdf + │ ├── data.csv + │ └── result.json + └── Timeline +``` + +--- + +# 94. File Detail UI + +```text +File + ├── Preview + ├── Metadata + ├── Versions + ├── Relations + ├── Activity + └── Download +``` + +--- + +# 95. File Permissions + +建议: + +```text +file.read +file.create +file.update +file.delete +file.download +file.preview +file.export +``` + +Artifact: + +```text +artifact.read +artifact.create +artifact.delete +artifact.download +``` + +--- + +# 96. Resource Scope + +File 默认继承: + +```text +Organization +Project +Resource Owner +``` + +例如: + +```text +Task + └── Artifact +``` + +Artifact 默认继承: + +```text +Task Scope +``` + +不能因为拿到了: + +```text +artifactId +``` + +就访问。 + +--- + +# 97. Signed URL Authorization + +生成 URL 时: + +```text +Permission ++ +Scope ++ +File Status +``` + +必须全部通过。 + +URL 生成后: + +```text +短时间有效 +``` + +--- + +# 98. Artifact Download From Agent + +Agent: + +```text +Task + ↓ +Artifact + ↓ +Capability + ↓ +Temporary URL +``` + +不要把: + +```text +permanent public URL +``` + +放进 Agent Context。 + +--- + +# 99. File Search Integration + +```text +File + ↓ +Text Extraction + ↓ +Search Runtime + ↓ +Global Search +``` + +Global Search 可以显示: + +```text +PDF +Article +Task +Deployment +``` + +统一结果。 + +--- + +# 100. File to Resource Relation + +例如: + +```text +seo.article + └── coverImage → core.file +``` + +```text +core.task + └── artifacts → core.artifact +``` + +```text +core.deployment + └── package → core.artifact +``` + +--- + +# 101. Plugin File Extension + +Plugin 可以注册: + +```ts +export interface FileExtension { + resource: string + + uploadPolicy?: UploadPolicy + + processors?: string[] + + previewProviders?: string[] + + metadata?: Record +} +``` + +--- + +# 102. SEO Plugin Example + +SEO Plugin: + +```text +seo.article + ├── coverImage + ├── attachments + └── generatedReport +``` + +系统自动使用: + +```text +File Runtime +Artifact Runtime +Search Runtime +``` + +无需 SEO Plugin 自己实现文件系统。 + +--- + +# 103. Deployment Example + +Deployment: + +```text +Build + ↓ +Artifact + ↓ +deployment.package + ↓ +Server +``` + +Artifact: + +```text +app.tar.gz +``` + +必须记录: + +```text +commit +build +runtime +plugin +checksum +``` + +这样可以: + +```text +rollback +``` + +--- + +# 104. Backup Example + +Backup: + +```text +Backup Task + ↓ +Job + ↓ +Artifact +``` + +Artifact: + +```text +backup-2026-09-11.tar.zst +``` + +保留: + +```text +provenance +checksum +retention +``` + +--- + +# 105. Import Example + +结合 Document 14: + +```text +User + ↓ +Upload CSV + ↓ +File + ↓ +Import Task + ↓ +Jobs + ↓ +Validate + ↓ +Import +``` + +错误: + +```text +import-errors.csv +``` + +作为: + +```text +Artifact +``` + +返回给用户。 + +--- + +# 106. Export Example + +```text +Resource Query + ↓ +Export Task + ↓ +Cursor + ↓ +Worker + ↓ +CSV + ↓ +Artifact +``` + +用户看到: + +```text +Export completed + ↓ +Download +``` + +--- + +# 107. AI Generated Content + +Agent: + +```text +Goal + ↓ +Generate Article + ↓ +Action + ↓ +Artifact +``` + +例如: + +```text +article.md +article.html +seo-report.json +``` + +这些必须是: + +```text +Artifacts +``` + +而不是: + +```text +/tmp/xxx +``` + +--- + +# 108. Agent Working Files + +Agent 可以有: + +```text +Working Files +``` + +但生命周期必须绑定: + +```text +AgentRun +``` + +例如: + +```text +AgentRun + └── workspace +``` + +Agent Run 结束后: + +```text +cleanup +``` + +除非: + +```text +promoted to Artifact +``` + +--- + +# 109. Workspace + +可以定义: + +```text +core.workspace +``` + +用于: + +```text +Agent +Build +Task +Plugin +``` + +但 Workspace 仍然必须经过: + +```text +Storage Runtime +``` + +--- + +# 110. Workspace Lifecycle + +```text +created + ↓ +active + ↓ +idle + ↓ +expired + ↓ +cleanup +``` + +--- + +# 111. Workspace Quota + +每个: + +```text +AgentRun +Task +Organization +``` + +可以有: + +```text +storage quota +``` + +例如: + +```ts +interface StorageQuota { + maxBytes: number + + maxFiles: number + + maxSingleFileBytes: number +} +``` + +--- + +# 112. Agent Budget Integration + +Agent Budget 增加: + +```ts +storageBytes?: number + +fileCount?: number + +uploadBytes?: number +``` + +因此: + +```text +Agent +``` + +不能无限产生: + +```text +10GB +``` + +文件。 + +--- + +# 113. Task Budget Integration + +Task 可以: + +```text +maxArtifactBytes +maxArtifactCount +``` + +超过: + +```text +budget_exceeded +``` + +Task 可以: + +```text +failed +``` + +或: + +```text +partially_completed +``` + +--- + +# 114. File Concurrency + +Storage Provider 需要: + +```text +upload concurrency +download concurrency +processing concurrency +``` + +特别是: + +```text +large files +``` + +避免 Worker 被单个任务占满。 + +--- + +# 115. Large File Streaming + +禁止: + +```ts +const buffer = await file.arrayBuffer() +``` + +处理巨大文件。 + +必须支持: + +```text +stream +``` + +例如: + +```ts +interface StreamSource { + stream(): ReadableStream +} +``` + +--- + +# 116. Streaming Copy + +例如: + +```text +S3 + ↓ +S3 +``` + +可以: + +```text +stream +``` + +不必: + +```text +S3 + ↓ +RAM + ↓ +S3 +``` + +--- + +# 117. Memory Limits + +File processor 必须有: + +```text +maxMemory +maxDuration +maxOutputSize +``` + +避免: + +```text +malicious archive +huge decompression +``` + +导致 Worker OOM。 + +--- + +# 118. Archive Safety + +ZIP/TAR 等处理必须防御: + +```text +Zip Bomb +Path Traversal +Symlink Escape +Huge File Count +Huge Uncompressed Size +``` + +--- + +# 119. Archive Extraction + +默认: + +```text +disabled +``` + +需要明确: + +```text +processor capability +``` + +并且: + +```text +sandbox +resource limit +``` + +--- + +# 120. File Conversion + +支持: + +```text +PDF → Text +DOCX → Text +Markdown → HTML +Image → Thumbnail +CSV → JSON +``` + +通过: + +```text +File Processor +``` + +执行。 + +--- + +# 121. Conversion Artifact + +转换后的结果: + +```text +source.pdf + ↓ +conversion + ↓ +source.txt +``` + +必须: + +```text +new Artifact +``` + +并记录: + +```text +derived_from +``` + +--- + +# 122. File Version vs Artifact Version + +区别: + +```text +File Version +``` + +表示: + +```text +同一个逻辑文件的更新 +``` + +而: + +```text +Artifact Version +``` + +表示: + +```text +同一个输出对象的不同生成版本 +``` + +不能混为一谈。 + +--- + +# 123. File Version Example + +```text +article.md +v1 +v2 +v3 +``` + +用户编辑: + +```text +v3 +``` + +Artifact: + +```text +SEO Report +v1 +v2 +``` + +每次 Task 重新生成。 + +--- + +# 124. Immutable Artifact + +默认: + +```text +Artifact immutable +``` + +如果需要修改: + +```text +create new version +``` + +而不是: + +```text +overwrite +``` + +--- + +# 125. Immutable Deployment Artifact + +Deployment package: + +```text +app-build-123.tar.gz +``` + +必须: + +```text +immutable +``` + +这样: + +```text +Deployment +``` + +才能可靠 rollback。 + +--- + +# 126. Artifact Promotion + +Artifact 可以: + +```text +temporary + ↓ +validated + ↓ +promoted + ↓ +production +``` + +例如: + +```text +Build Artifact + ↓ +Test + ↓ +Production Artifact +``` + +Promotion 必须记录: + +```text +who +when +from +to +``` + +--- + +# 127. Artifact Signature + +未来支持: + +```text +artifact signature +``` + +用于: + +```text +deployment +supply chain +verification +``` + +接口预留: + +```ts +interface ArtifactSignature { + algorithm: string + + keyId: string + + signature: string + + signedAt: Date +} +``` + +第一阶段不需要自行实现密码学。 + +--- + +# 128. Storage Audit + +记录: + +```text +file.created +file.read +file.downloaded +file.deleted +artifact.created +artifact.downloaded +``` + +对于敏感文件: + +```text +read audit +``` + +必须开启。 + +--- + +# 129. Data / File Separation + +Document 14: + +```text +Data Runtime +``` + +负责: + +```text +metadata +query +search +relations +``` + +Document 15: + +```text +Storage Runtime +``` + +负责: + +```text +binary +blob +upload +download +artifact +``` + +不要把 Blob: + +```text +直接塞 PostgreSQL +``` + +除非明确的小文件场景。 + +--- + +# 130. Database Storage + +默认: + +```text +PostgreSQL +``` + +保存: + +```text +File Metadata +Artifact Metadata +Upload Session +File Relations +Retention Policy +``` + +对象存储保存: + +```text +Blob +``` + +--- + +# 131. Recommended Architecture + +```text +PostgreSQL + ├── core.file + ├── core.artifact + ├── core.artifact_version + ├── core.upload_session + ├── core.file_text + └── core.file_relation + +Object Storage + ├── private + ├── artifact + ├── temporary + └── backup +``` + +--- + +# 132. Storage Database Schema + +建议至少: + +```text +files +artifacts +artifact_versions +upload_sessions +file_relations +file_processing_jobs +storage_objects +``` + +--- + +# 133. storage_objects + +```ts +interface StorageObjectRecord { + id: string + + provider: string + + bucket: string + + key: string + + size: number + + checksum?: string + + etag?: string + + contentType?: string + + createdAt: Date +} +``` + +--- + +# 134. File → Storage Object + +```text +File + ↓ +StorageObject + ↓ +Provider + ↓ +Blob +``` + +允许未来: + +```text +File +``` + +重新绑定新的: + +```text +StorageObject +``` + +而不修改 File ID。 + +--- + +# 135. Storage Migration + +Provider 切换: + +```text +S3 + ↓ +R2 +``` + +流程: + +```text +Migration Task + ↓ +Read Storage Object + ↓ +Copy + ↓ +Verify checksum + ↓ +Update metadata + ↓ +Delete old object +``` + +必须支持: + +```text +resume +retry +checkpoint +``` + +--- + +# 136. Storage Replication + +未来支持: + +```text +Primary + + +Replica +``` + +例如: + +```text +S3 + ↓ +Backup S3 +``` + +Artifact 可以配置: + +```text +replication policy +``` + +--- + +# 137. Storage Disaster Recovery + +必须考虑: + +```text +DB lost +Object Storage lost +DB/Object inconsistent +``` + +恢复顺序: + +```text +Database + ↓ +Storage + ↓ +Reconcile + ↓ +Index +``` + +--- + +# 138. Reconciliation + +提供: + +```text +core.storage.reconcile +``` + +检查: + +```text +DB File exists +Storage Object exists +Checksum matches +Artifact reference valid +``` + +发现异常: + +```text +orphan +missing +corrupt +``` + +--- + +# 139. Reconciliation Task + +```text +Storage Reconcile + ↓ +Task + ↓ +Jobs + ↓ +Worker + ↓ +Report Artifact +``` + +例如: + +```text +100000 objects +99000 valid +800 orphan +200 missing +``` + +输出: + +```text +reconcile-report.json +``` + +--- + +# 140. Storage CLI + +```bash +devos storage providers + +devos storage health + +devos storage files + +devos storage objects + +devos storage reconcile + +devos storage gc + +devos storage migrate + +devos storage usage +``` + +Artifact: + +```bash +devos artifact list + +devos artifact get + +devos artifact versions +``` + +--- + +# 141. Storage UI + +Settings: + +```text +System + └── Storage + ├── Providers + ├── Buckets + ├── Usage + ├── Health + ├── Policies + └── Cleanup +``` + +--- + +# 142. Organization Storage Usage + +Dashboard: + +```text +Storage + ├── Files + ├── Artifacts + ├── Temporary + ├── Backups + └── Total +``` + +按: + +```text +Organization +Project +Plugin +Resource +``` + +统计。 + +--- + +# 143. Plugin Storage Usage + +Plugin 可以查看: + +```text +SEO Plugin + ├── 20GB + ├── 12000 files + └── 800 artifacts +``` + +但必须只能看到: + +```text +plugin-owned data +``` + +--- + +# 144. Storage Capability Registry + +Storage 相关能力: + +```text +core.file.upload +core.file.download +core.file.preview +core.file.search +core.file.delete + +core.artifact.create +core.artifact.list +core.artifact.download + +core.storage.health +core.storage.reconcile +core.storage.gc +``` + +全部进入: + +```text +Capability Registry +``` + +--- + +# 145. MCP Exposure + +MCP 可以使用: + +```text +file.search +file.get +artifact.list +artifact.get +``` + +但: + +```text +file.download +file.delete +``` + +属于更高风险 Capability。 + +必须经过: + +```text +Policy +Permission +Budget +Approval +``` + +--- + +# 146. Agent File Search Example + +Goal: + +```text +“找到之前生成的 SEO 报告” +``` + +Agent: + +```text +Goal + ↓ +Capability Discovery + ↓ +core.file.search + ↓ +Search Runtime + ↓ +Permission + ↓ +Results + ↓ +core.artifact.get +``` + +而不是: + +```text +Agent + ↓ +filesystem scan +``` + +--- + +# 147. Agent Artifact Example + +Goal: + +```text +“把本次分析结果导出为 PDF” +``` + +流程: + +```text +Agent + ↓ +Plan + ↓ +Task + ↓ +Generate Report Action + ↓ +Artifact + ↓ +Task Completed +``` + +最终: + +```text +Artifact ID +``` + +进入: + +```text +Agent Result +``` + +--- + +# 148. Plugin Example + +Plugin 只需要: + +```ts +defineResource({ + resource: 'seo.report' +}) +``` + +并声明: + +```text +attachment field +``` + +DevOS 自动提供: + +```text +upload +preview +download +search +artifact +retention +permission +``` + +--- + +# 149. UI Extension + +Plugin 可以声明: + +```ts +interface FileWidgetExtension { + resource: string + + placement: + | 'overview' + | 'attachments' + | 'artifacts' + + component: string +} +``` + +例如: + +```text +SEO Article + └── Attachments + ├── Cover + ├── Images + └── Research PDF +``` + +--- + +# 150. Package Structure + +```text +packages/storage/ +├── storage-runtime.ts +├── storage-context.ts +├── storage-provider.ts +├── storage-policy.ts +├── storage-registry.ts +├── providers/ +│ ├── local/ +│ ├── s3/ +│ └── r2/ +└── index.ts +``` + +--- + +# 151. File Package + +```text +packages/file/ +├── file-service.ts +├── file-resource.ts +├── upload/ +├── download/ +├── preview/ +├── processing/ +├── lifecycle/ +├── permissions/ +└── index.ts +``` + +--- + +# 152. Artifact Package + +```text +packages/artifact/ +├── artifact-service.ts +├── artifact-resource.ts +├── versioning.ts +├── provenance.ts +├── lineage.ts +├── retention.ts +└── index.ts +``` + +--- + +# 153. Processing Package + +```text +packages/file-processing/ +├── processor.ts +├── processor-registry.ts +├── pipeline.ts +├── security/ +├── metadata/ +├── preview/ +├── extraction/ +├── embedding/ +└── index.ts +``` + +--- + +# 154. Workspace Package + +```text +packages/workspace/ +├── workspace-runtime.ts +├── workspace-policy.ts +├── quota.ts +├── lifecycle.ts +└── index.ts +``` + +--- + +# 155. Acceptance Criteria + +## Storage + +```text +[ ] Storage Runtime +[ ] Storage Provider +[ ] Local Provider +[ ] S3-compatible Provider +[ ] Provider Registry +[ ] Presigned URL +[ ] Streaming +[ ] Checksum +``` + +## File + +```text +[ ] File Resource +[ ] Upload +[ ] Chunked Upload +[ ] Resume +[ ] Download +[ ] Preview +[ ] File Permissions +[ ] File Lifecycle +[ ] File Search +``` + +## Artifact + +```text +[ ] Artifact Resource +[ ] Artifact Version +[ ] Provenance +[ ] Lineage +[ ] Immutable Artifact +[ ] Artifact Download +[ ] Artifact Retention +``` + +## Processing + +```text +[ ] Processing Pipeline +[ ] Metadata +[ ] Text Extraction +[ ] Thumbnail +[ ] Security Scan +[ ] Embedding +[ ] Search Index +``` + +## Reliability + +```text +[ ] Retry +[ ] Checkpoint +[ ] Reconciliation +[ ] Garbage Collection +[ ] Storage Migration +[ ] Health Check +``` + +--- + +# 156. Security Tests + +必须测试: + +```text +User A cannot access User B file + +Org A cannot access Org B file + +Expired signed URL fails + +Quarantined file cannot download + +Quarantined file cannot preview + +Forbidden file cannot search + +Forbidden file cannot be indexed into accessible scope + +Path traversal blocked + +Absolute path blocked + +Symlink escape blocked + +Oversized upload rejected + +Invalid MIME rejected + +Archive bomb rejected + +Expired temporary file cleaned +``` + +--- + +# 157. Upload Tests + +测试: + +```text +small file upload +large file upload +multipart upload +resume +cancel +retry +checksum mismatch +duplicate upload +provider failure +network interruption +``` + +--- + +# 158. Artifact Tests + +测试: + +```text +artifact creation +artifact version +artifact provenance +artifact lineage +artifact immutability +artifact retention +artifact download +artifact permission +artifact rollback +``` + +--- + +# 159. Agent Tests + +测试: + +```text +Agent can search authorized files + +Agent cannot access unauthorized files + +Agent cannot read quarantined files + +Agent can create Artifact + +Agent Artifact has provenance + +Agent respects storage budget + +Agent working files are cleaned + +Artifact survives AgentRun cleanup +``` + +--- + +# 160. MCP Tests + +测试: + +```text +MCP file search +MCP file get +MCP artifact get +MCP permission +MCP scope +MCP signed URL expiry +MCP cannot access filesystem +``` + +--- + +# 161. Plugin Tests + +安装 Plugin: + +```text +Plugin + ↓ +Resource + ↓ +File Attachment + ↓ +Upload + ↓ +Preview + ↓ +Search + ↓ +Artifact +``` + +全部应该自动进入: + +```text +DevOS Runtime +``` + +--- + +# 162. Performance Tests + +必须测试: + +```text +100MB upload +1GB upload +10GB artifact +100k files +1M files +large directory +large search index +large artifact list +``` + +重点: + +```text +RAM usage +CPU +network +database query +provider latency +``` + +--- + +# 163. Zcode Implementation Rules + +## Rule 1 + +所有文件二进制操作: + +```text +必须经过 Storage Runtime +``` + +--- + +## Rule 2 + +禁止: + +```text +UI +Plugin +Agent +MCP +Action Controller +``` + +直接: + +```text +fs.readFile +fs.writeFile +S3 SDK +``` + +访问业务文件。 + +--- + +## Rule 3 + +业务文件 Metadata: + +```text +PostgreSQL +``` + +文件 Blob: + +```text +Object Storage +``` + +默认分离。 + +--- + +## Rule 4 + +Artifact 必须可追踪: + +```text +Task +Job +Execution +Action Version +Plugin Version +Runtime Version +``` + +--- + +## Rule 5 + +Artifact 默认: + +```text +Immutable +``` + +修改必须产生: + +```text +New Version +``` + +--- + +## Rule 6 + +大文件必须: + +```text +Streaming +Multipart +Presigned URL +``` + +--- + +## Rule 7 + +文件权限必须在: + +```text +URL Generation +Preview +Download +Search +MCP +Agent +``` + +全部生效。 + +--- + +## Rule 8 + +Storage Index / Cache / Metadata: + +```text +都不是 Blob Source of Truth +``` + +--- + +## Rule 9 + +文件生命周期必须: + +```text +Task ++ +Job ++ +Worker ++ +Scheduler +``` + +执行。 + +--- + +## Rule 10 + +Storage Provider 必须可替换。 + +禁止业务代码依赖: + +```text +S3 SDK +MinIO SDK +R2 SDK +``` + +--- + +# 164. Golden Rule + +DevOS 文件体系必须遵循: + +```text +File + ↓ +File Metadata + ↓ +Storage Runtime + ↓ +Storage Provider + ↓ +Blob +``` + +Task 产物: + +```text +Task + ↓ +Job + ↓ +Execution + ↓ +Artifact + ↓ +Artifact Version + ↓ +File + ↓ +Storage Object + ↓ +Blob +``` + +文件处理: + +```text +File + ↓ +Processing Task + ↓ +Processor + ├── Security Scan + ├── Metadata + ├── Preview + ├── Text Extraction + ├── Embedding + └── Search Index +``` + +最终形成: + +```text + DevOS File System + │ + ┌─────────────────┼─────────────────┐ + │ │ │ + File Artifact Workspace + │ │ │ + └─────────────────┼─────────────────┘ + │ + Storage Runtime + │ + ┌───────────┴───────────┐ + │ │ + Metadata Blob + │ │ + PostgreSQL Object Storage + │ │ + └───────────┬───────────┘ + │ + Processing Runtime + │ + ┌─────────────────┼─────────────────┐ + │ │ │ + Preview Extract Embedding + │ │ │ + └─────────────────┼─────────────────┘ + │ + Search Runtime + │ + Global Search + │ + ┌───────────┴───────────┐ + │ │ + User Agent + │ │ + MCP Plugin +``` + +--- + +# 165. Final Principle + +DevOS 不应该让 Plugin 自己实现: + +```text +Upload +Download +File Storage +S3 +Preview +Artifact +File Search +File Permission +File Lifecycle +``` + +而应该: + +```text +DevOS Core + └── Storage Runtime + ├── File + ├── Artifact + ├── Workspace + ├── Upload + ├── Preview + ├── Processing + ├── Search + └── Lifecycle +``` + +Plugin 只定义: + +```text +Resource ++ +Attachment ++ +Artifact Type ++ +Processing Requirement +``` + +DevOS 自动提供基础设施。 + +最终目标: + +```text +Plugin = Business Capability + +DevOS = Data + Action + Agent + Task + Storage + Runtime +``` + +而不是: + +```text +Plugin = 一个自己带数据库、文件系统、队列、Agent、搜索系统的小型应用 +``` + +这才是 DevOS 可以长期复用、扩展和 Fork 的基础。 diff --git a/Docs/DevOS-Platform-v2/16_EVENT_STREAMING_NOTIFICATION_REALTIME_RUNTIME.md b/Docs/DevOS-Platform-v2/16_EVENT_STREAMING_NOTIFICATION_REALTIME_RUNTIME.md new file mode 100644 index 0000000..74464ad --- /dev/null +++ b/Docs/DevOS-Platform-v2/16_EVENT_STREAMING_NOTIFICATION_REALTIME_RUNTIME.md @@ -0,0 +1,5782 @@ +# DevOS 16 — Event / Streaming / Notification / Realtime Runtime + +> Version: 1.0 +> Status: Implementation Specification +> Target: Zcode +> Depends on: +> - 03_RESOURCE_ACTION_MODEL.md +> - 06_MCP_SKILL_AGENT_RUNTIME.md +> - 09_TASK_JOB_QUEUE_RUNTIME.md +> - 12_MIGRATION_VERSIONING_COMPATIBILITY.md +> - 14_DATA_QUERY_SEARCH_INDEX_RUNTIME.md +> - 15_FILE_ARTIFACT_STORAGE_RUNTIME.md + +--- + +# 1. Document Purpose + +本文件定义 DevOS 的统一: + +- Event Runtime +- Event Bus +- Event Store +- Event Subscription +- Event Handler +- Event Delivery +- Event Replay +- Webhook Runtime +- Notification Runtime +- Realtime Runtime +- WebSocket +- SSE +- Task Progress Streaming +- Agent Observation Streaming +- Plugin Event Integration +- MCP Event Integration + +目标是让整个 DevOS 使用同一套事件与实时通信基础设施。 + +核心原则: + +```text +Action + ↓ +Execution + ↓ +Domain Event + ↓ +Event Runtime + ├── Event Handler + ├── Task + ├── Search Index + ├── Cache + ├── Notification + ├── Webhook + ├── Agent + ├── Plugin + └── Realtime +```` + +任何模块都不得自己实现第二套 Event Bus。 + +--- + +# 2. Core Philosophy + +DevOS 中必须区分: + +```text +Event +Event Delivery +Notification +Realtime Message +Webhook +``` + +它们不是同一个概念。 + +--- + +## 2.1 Event + +Event 表示: + +> 系统中已经发生了一件事情。 + +例如: + +```text +user.created +seo.website.scanned +task.completed +job.failed +artifact.created +plugin.installed +server.deployed +``` + +Event 是事实。 + +--- + +# 2.2 Event Handler + +Handler 表示: + +> 某个模块希望对某个 Event 做事情。 + +例如: + +```text +task.completed + ↓ +create notification +``` + +或者: + +```text +seo.website.scanned + ↓ +update search index +``` + +--- + +# 2.3 Notification + +Notification 表示: + +> 系统希望某个用户/Agent/系统知道某件事情。 + +例如: + +```text +通知: +SEO Scan completed +``` + +Notification 是用户体验层。 + +--- + +# 2.4 Realtime Message + +Realtime Message 表示: + +> 系统需要立即把状态变化推送给在线客户端。 + +例如: + +```text +Task progress: +37% +``` + +它不一定需要永久保存。 + +--- + +# 2.5 Webhook + +Webhook 表示: + +> 把 DevOS Event 推送给外部系统。 + +例如: + +```text +task.completed + ↓ +https://example.com/webhook +``` + +--- + +# 3. Unified Architecture + +整体结构: + +```text + ┌─────────────────────┐ + │ Action │ + └──────────┬──────────┘ + │ + ▼ + ┌─────────────────────┐ + │ Execution │ + └──────────┬──────────┘ + │ + ▼ + ┌─────────────────────┐ + │ Event Runtime │ + └──────────┬──────────┘ + │ + ┌──────────────────────┼──────────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌────────────┐ ┌────────────┐ ┌────────────┐ + │ Event Bus │ │ Event Store│ │ Event Outbox│ + └─────┬──────┘ └────────────┘ └────────────┘ + │ + ├──────────────┬──────────────┬──────────────┐ + │ │ │ │ + ▼ ▼ ▼ ▼ + Handler Notification Webhook Realtime + │ │ │ │ + ▼ ▼ ▼ ▼ + Task In-App/Email External WS/SSE + │ + ▼ + Agent Runtime +``` + +--- + +# 4. Event Types + +DevOS Event 至少分为四类。 + +```text +Domain Event +Integration Event +System Event +Lifecycle Event +``` + +--- + +## 4.1 Domain Event + +描述业务事实。 + +例如: + +```text +seo.website.created +seo.website.scanned +seo.keyword.updated +crm.customer.created +content.article.published +``` + +--- + +## 4.2 Integration Event + +用于模块之间或外部系统之间通信。 + +例如: + +```text +github.repository.synced +stripe.payment.completed +slack.message.received +``` + +--- + +## 4.3 System Event + +系统基础设施事件。 + +例如: + +```text +worker.started +worker.stopped +queue.overloaded +storage.degraded +database.connection.failed +``` + +--- + +## 4.4 Lifecycle Event + +DevOS 对象生命周期事件。 + +例如: + +```text +resource.created +resource.updated +resource.deleted + +task.created +task.started +task.completed + +job.created +job.started +job.completed +job.failed + +execution.started +execution.completed +execution.failed +``` + +--- + +# 5. Event Naming + +统一使用: + +```text +.. +``` + +例如: + +```text +core.user.created + +core.task.created +core.task.started +core.task.completed +core.task.failed + +core.job.started +core.job.completed + +seo.website.created +seo.website.scanned + +devops.server.deployed +``` + +禁止: + +```text +userCreated +UserCreated +createdUser +taskDone +``` + +推荐: + +```text +core.user.created +core.task.completed +``` + +--- + +# 6. Event Version + +Event 必须支持版本。 + +格式: + +```text +eventType +eventVersion +``` + +例如: + +```text +core.task.completed +version: 1 +``` + +未来: + +```text +core.task.completed +version: 2 +``` + +禁止直接破坏旧 Event Contract。 + +--- + +# 7. Event Envelope + +所有 Event 使用统一 Envelope。 + +```ts +export interface DevOSEvent { + id: string + + type: string + + version: number + + occurredAt: string + + publishedAt?: string + + actor: EventActor + + organizationId?: string + + projectId?: string + + environment?: string + + resource?: EventResourceRef + + payload: T + + metadata?: Record + + correlationId?: string + + causationId?: string + + requestId?: string + + executionId?: string + + taskId?: string + + jobId?: string +} +``` + +--- + +# 8. Event Actor + +```ts +export interface EventActor { + type: + | "user" + | "agent" + | "service" + | "system" + + id?: string + + name?: string +} +``` + +例如: + +```json +{ + "type": "agent", + "id": "agent_123" +} +``` + +--- + +# 9. Event Resource Reference + +```ts +export interface EventResourceRef { + type: string + id: string +} +``` + +例如: + +```json +{ + "type": "seo.website", + "id": "site_123" +} +``` + +--- + +# 10. Correlation / Causation + +DevOS 必须支持事件链追踪。 + +例如: + +```text +User + ↓ +Agent Goal + ↓ +Task + ↓ +Job + ↓ +Action + ↓ +Execution + ↓ +Event + ↓ +Handler + ↓ +Notification +``` + +使用: + +```text +correlationId +causationId +``` + +--- + +## 10.1 correlationId + +表示: + +> 整个业务流程属于哪个 Trace。 + +--- + +## 10.2 causationId + +表示: + +> 当前 Event 是由哪个 Event / Execution 导致的。 + +--- + +# 11. Event Bus + +定义统一 EventBus: + +```ts +export interface EventBus { + publish( + event: DevOSEvent + ): Promise + + publishMany( + events: DevOSEvent[] + ): Promise + + subscribe( + subscription: EventSubscription + ): Promise + + unsubscribe( + subscriptionId: string + ): Promise +} +``` + +--- + +# 12. Event Subscription + +```ts +export interface EventSubscription { + id: string + + name: string + + eventTypes: string[] + + handlerId: string + + filter?: EventFilter + + enabled: boolean + + concurrency?: number + + retryPolicy?: RetryPolicy + + metadata?: Record +} +``` + +--- + +# 13. Event Filter + +订阅不能只支持 Event Type。 + +必须支持条件过滤。 + +例如: + +```text +event.type = "core.task.completed" +AND +event.organizationId = "org_123" +``` + +接口: + +```ts +export interface EventFilter { + expression?: string + + fields?: Record< + string, + unknown + > +} +``` + +建议第一版支持: + +```text +eq +neq +in +notIn +contains +startsWith +exists +``` + +--- + +# 14. Event Handler + +```ts +export interface EventHandler { + id: string + + name: string + + eventTypes: string[] + + handle( + event: DevOSEvent, + context: EventHandlerContext + ): Promise +} +``` + +Context: + +```ts +export interface EventHandlerContext { + requestId: string + + correlationId?: string + + organizationId?: string + + signal: AbortSignal + + logger: Logger +} +``` + +--- + +# 15. Handler 不允许直接做危险业务操作 + +Handler 不应该: + +```ts +db.user.delete() +``` + +也不应该: + +```ts +server.exec() +``` + +必须: + +```text +Event + ↓ +Handler + ↓ +Action Runtime +``` + +例如: + +```ts +await actionRuntime.execute( + "seo.website.reindex", + input, + context +) +``` + +--- + +# 16. Event Delivery + +Event 发布后不应该直接同步执行所有 Handler。 + +推荐: + +```text +publish + ↓ +Event Outbox + ↓ +Event Queue + ↓ +Event Worker + ↓ +Handler +``` + +这样可以: + +* retry +* DLQ +* concurrency +* backpressure +* replay +* observability + +--- + +# 17. Outbox Pattern + +这是 DevOS 的关键一致性机制。 + +错误方式: + +```text +DB Transaction + ↓ +commit + +EventBus.publish() + ↓ +failed +``` + +这样会出现: + +```text +数据库已经成功 +Event 没有发送 +``` + +--- + +正确方式: + +```text +DB Transaction + ├── Business Data + └── Outbox Event + ↓ + COMMIT + ↓ + Outbox Worker + ↓ + Event Bus +``` + +--- + +# 18. Outbox Schema + +```ts +export interface EventOutboxRecord { + id: string + + eventId: string + + eventType: string + + eventVersion: number + + payload: unknown + + status: + | "pending" + | "published" + | "failed" + + attempts: number + + nextAttemptAt?: Date + + createdAt: Date + + publishedAt?: Date + + lastError?: string +} +``` + +--- + +# 19. Inbox Pattern + +对于需要严格幂等的 Consumer: + +```text +Event + ↓ +Inbox + ↓ +check eventId + ↓ +already processed? + ├── yes → skip + └── no + ↓ + process + ↓ + mark processed +``` + +接口: + +```ts +export interface EventInboxRecord { + consumerId: string + + eventId: string + + processedAt: Date + + result?: unknown +} +``` + +唯一索引: + +```text +(consumerId, eventId) +``` + +--- + +# 20. Event Idempotency + +默认: + +```text +At-Least-Once Delivery +``` + +而不是: + +```text +Exactly-Once +``` + +因此 Handler 必须幂等。 + +例如: + +```ts +if (await inbox.exists(event.id)) { + return +} +``` + +--- + +# 21. Retry + +Event Handler 支持: + +```text +fixed +linear +exponential +``` + +例如: + +```text +1s +5s +30s +2m +10m +``` + +失败后: + +```text +retry + ↓ +retry + ↓ +retry + ↓ +DLQ +``` + +--- + +# 22. Dead Letter Queue + +Event DLQ: + +```ts +export interface EventDeadLetter { + id: string + + eventId: string + + subscriptionId: string + + handlerId: string + + event: DevOSEvent + + error: unknown + + attempts: number + + failedAt: Date + + metadata?: Record +} +``` + +支持: + +```text +view +retry +retry selected +retry all +discard +export +``` + +--- + +# 23. Event Replay + +Event Store 必须支持 Replay。 + +用途: + +```text +重新建立 Search Index +重新计算统计 +恢复插件状态 +调试 Handler +数据迁移 +``` + +Replay: + +```text +Event Store + ↓ +filter + ↓ +Replay + ↓ +Event Bus + ↓ +Selected Handler +``` + +Replay 必须支持: + +```text +event type +date range +organization +resource +event id +handler +``` + +--- + +# 24. Replay Safety + +Replay 默认: + +```text +DO NOT execute destructive actions +``` + +除非明确允许。 + +例如: + +```ts +handler.metadata.replaySafe = true +``` + +对于: + +```text +delete +deploy +payment +send email +send webhook +``` + +默认禁止 replay。 + +--- + +# 25. Event Ordering + +不要假设全局事件顺序。 + +只保证指定 Partition 内顺序。 + +推荐 Partition Key: + +```text +organizationId +resourceId +taskId +``` + +例如: + +```text +task_123 +``` + +相关事件: + +```text +task.created +task.started +task.progress +task.completed +``` + +必须保持顺序。 + +--- + +# 26. Event Partition + +```ts +export interface EventPartitionStrategy { + getPartitionKey( + event: DevOSEvent + ): string +} +``` + +默认: + +```text +resource.id +``` + +如果没有: + +```text +organizationId +``` + +--- + +# 27. Event Store + +Event Store 用于: + +* 审计 +* Debug +* Replay +* Timeline +* Agent observation +* Plugin events +* Integration + +定义: + +```ts +export interface EventStore { + append( + event: DevOSEvent + ): Promise + + get( + id: string + ): Promise + + query( + input: EventQuery + ): Promise + + replay( + input: EventReplayInput + ): Promise +} +``` + +--- + +# 28. Event Query + +```ts +export interface EventQuery { + types?: string[] + + organizationId?: string + + projectId?: string + + resourceType?: string + + resourceId?: string + + actorType?: string + + actorId?: string + + correlationId?: string + + from?: Date + + to?: Date + + cursor?: string + + limit?: number +} +``` + +--- + +# 29. Event Timeline + +任何核心 Resource 都应该能够查看 Timeline: + +```text +Task #123 + +22:01 created +22:01 queued +22:02 started +22:03 progress 20% +22:04 progress 60% +22:06 completed +``` + +Timeline 数据来源: + +```text +Event Store +``` + +而不是 UI 自己维护。 + +--- + +# 30. Notification Runtime + +Notification 是 Event 的用户体验层。 + +架构: + +```text +Event + ↓ +Notification Rule + ↓ +Notification Runtime + ↓ +Channel +``` + +支持: + +```text +in-app +email +webhook +push +``` + +未来可扩展: + +```text +Slack +Discord +Telegram +SMS +``` + +--- + +# 31. Notification + +```ts +export interface Notification { + id: string + + organizationId?: string + + recipientType: + | "user" + | "agent" + | "organization" + + recipientId: string + + type: string + + title: string + + body: string + + severity: + | "info" + | "success" + | "warning" + | "error" + + readAt?: Date + + createdAt: Date + + data?: Record + + sourceEventId?: string + + actionUrl?: string +} +``` + +--- + +# 32. Notification Channels + +定义: + +```ts +export interface NotificationChannel { + id: string + + type: + | "in_app" + | "email" + | "webhook" + | "push" + + send( + notification: Notification + ): Promise +} +``` + +--- + +# 33. Notification Preferences + +用户可以设置: + +```text +Task Completed + In-App: ON + Email: ON + +Task Failed + In-App: ON + Email: ON + +Task Progress + In-App: ON + Email: OFF + +System Warning + In-App: ON + Email: ON +``` + +Preference Resource: + +```text +core.notificationPreference +``` + +--- + +# 34. Notification Rule + +系统管理员 / Plugin 可以定义: + +```ts +export interface NotificationRule { + id: string + + eventTypes: string[] + + recipientResolver: string + + templateId: string + + channels: string[] + + filter?: EventFilter + + enabled: boolean +} +``` + +例如: + +```text +core.task.failed + ↓ +Task Owner + ↓ +in_app + email +``` + +--- + +# 35. Notification Template + +模板必须支持: + +```text +title +body +variables +locale +``` + +例如: + +```text +Title: +Task {{task.name}} failed + +Body: +Task {{task.id}} failed because: +{{error.message}} +``` + +--- + +# 36. Notification Center + +前端必须提供统一 Notification Center。 + +包含: + +```text +All +Unread +Mentions +Tasks +System +Plugin +``` + +支持: + +```text +mark read +mark unread +mark all read +delete +open +``` + +--- + +# 37. Realtime Runtime + +Realtime Runtime 用于: + +```text +WebSocket +SSE +``` + +统一抽象: + +```ts +export interface RealtimeRuntime { + publish( + channel: string, + message: RealtimeMessage + ): Promise + + subscribe( + connection: RealtimeConnection, + channel: string + ): Promise + + unsubscribe( + connection: RealtimeConnection, + channel: string + ): Promise +} +``` + +--- + +# 38. Realtime Message + +```ts +export interface RealtimeMessage { + id: string + + type: string + + channel: string + + timestamp: string + + payload: T + + eventId?: string +} +``` + +--- + +# 39. Channels + +推荐: + +```text +user:{userId} + +organization:{organizationId} + +project:{projectId} + +task:{taskId} + +job:{jobId} + +agent-run:{runId} + +resource:{resourceType}:{resourceId} +``` + +例如: + +```text +task:task_123 +``` + +--- + +# 40. Channel Authorization + +客户端订阅: + +```text +task:task_123 +``` + +必须检查: + +```text +User Permission ++ +Resource Permission ++ +Organization Scope ++ +Project Scope +``` + +禁止: + +```text +client.subscribe("task:someone_else") +``` + +直接获取数据。 + +--- + +# 41. WebSocket + +WebSocket 适用于: + +```text +双向通信 +Agent Chat +实时控制 +Interactive UI +``` + +例如: + +```text +Browser + ↕ +WebSocket + ↕ +Realtime Runtime +``` + +--- + +# 42. SSE + +SSE 适用于: + +```text +Server → Browser +``` + +特别适合: + +```text +Task Progress +Agent Output +Logs +Execution Events +Streaming Text +``` + +例如: + +```text +GET /api/tasks/:id/stream +``` + +服务器发送: + +```text +event: task.progress +data: {...} +``` + +--- + +# 43. Task Streaming + +Task 必须支持实时观察。 + +```text +Task + ↓ +Events + ↓ +Realtime + ↓ +UI +``` + +客户端: + +```text +Task created +Task queued +Task started +Task progress +Task log +Task artifact +Task completed +``` + +--- + +# 44. Agent Streaming + +Agent Runtime 必须支持: + +```text +Goal created +Plan created +Step started +Capability selected +Action started +Action completed +Observation +Replan +Completed +``` + +但: + +> 不允许向客户端暴露模型隐藏 Chain-of-Thought。 + +只允许: + +```text +decision summary +action +status +result +reason summary +``` + +例如: + +```json +{ + "type": "agent.step", + "status": "running", + "summary": "正在检查网站当前索引状态" +} +``` + +禁止保存: + +```text +完整内部思维链 +``` + +--- + +# 45. Agent Observation + +Agent 可以订阅: + +```text +task events +job events +action events +resource events +plugin events +``` + +然后: + +```text +Event + ↓ +Agent Observation + ↓ +Agent Runtime + ↓ +Continue / Replan / Finish +``` + +--- + +# 46. Plugin Event Integration + +Plugin Manifest 可以声明: + +```json +{ + "events": { + "subscribe": [ + "core.task.completed", + "seo.website.scanned" + ], + "publish": [ + "seo.website.scanned" + ] + } +} +``` + +安装 Plugin 后: + +```text +Plugin + ↓ +Event Registry +``` + +自动注册。 + +--- + +# 47. Plugin Event Handler + +Plugin 可以定义: + +```ts +export default { + events: { + "seo.website.scanned": async (event, ctx) => { + // ... + } + } +} +``` + +但是最终执行仍然必须: + +```text +Handler + ↓ +Action Runtime +``` + +--- + +# 48. MCP Event Integration + +MCP Server 不应该绕过 Event Runtime。 + +MCP 可以: + +```text +read events +subscribe events +trigger actions +``` + +例如: + +```text +mcp.devos.events.search +mcp.devos.events.subscribe +``` + +但是: + +```text +MCP + ↓ +Capability + ↓ +Action Runtime / Event Runtime +``` + +--- + +# 49. Webhook Runtime + +Webhook 是 Event Runtime 的外部出口。 + +架构: + +```text +Event + ↓ +Webhook Subscription + ↓ +Webhook Delivery + ↓ +HTTP +``` + +--- + +# 50. Webhook Subscription + +```ts +export interface WebhookSubscription { + id: string + + name: string + + url: string + + eventTypes: string[] + + secret: string + + enabled: boolean + + headers?: Record + + retryPolicy?: RetryPolicy +} +``` + +--- + +# 51. Webhook Security + +Webhook 必须签名。 + +例如: + +```text +X-DevOS-Signature +X-DevOS-Event +X-DevOS-Timestamp +``` + +推荐: + +```text +HMAC-SHA256 +``` + +签名内容: + +```text +timestamp + "." + rawBody +``` + +接收方必须验证: + +```text +signature +timestamp +replay window +``` + +--- + +# 52. Webhook Retry + +失败: + +```text +2xx + ↓ +success + +4xx + ↓ +通常不 retry + +5xx + ↓ +retry + +timeout + ↓ +retry +``` + +支持: + +```text +exponential backoff +jitter +max attempts +``` + +--- + +# 53. Webhook Delivery Resource + +```text +core.webhookDelivery +``` + +字段: + +```ts +export interface WebhookDelivery { + id: string + + subscriptionId: string + + eventId: string + + status: + | "pending" + | "sending" + | "delivered" + | "failed" + + attempts: number + + responseStatus?: number + + responseBody?: string + + lastError?: string + + createdAt: Date + + deliveredAt?: Date +} +``` + +--- + +# 54. Event → Notification → Realtime + +三者必须统一。 + +例如: + +```text +task.completed + │ + ├──────────────→ Event Store + │ + ├──────────────→ Notification + │ │ + │ ├── In-App + │ └── Email + │ + ├──────────────→ Realtime + │ │ + │ └── Browser + │ + └──────────────→ Webhook +``` + +禁止: + +```text +Task Service + ├── sendWebSocket() + ├── sendEmail() + ├── sendWebhook() + └── createNotification() +``` + +Task Service 只应该: + +```text +publish Event +``` + +--- + +# 55. Event Triggered Task + +Event 可以创建 Task。 + +例如: + +```text +server.health.failed + ↓ +Event Handler + ↓ +Task + ↓ +Agent + ↓ +diagnose server +``` + +或者: + +```text +seo.website.scan.completed + ↓ +create analysis task +``` + +--- + +# 56. Event Triggered Agent + +支持: + +```text +Event + ↓ +Agent Trigger + ↓ +Goal + ↓ +Agent Runtime +``` + +定义: + +```ts +export interface AgentEventTrigger { + id: string + + eventTypes: string[] + + agentProfileId: string + + goalTemplate: string + + filter?: EventFilter + + enabled: boolean +} +``` + +例如: + +```text +Event: +seo.website.scan.failed + +Agent: +SEO Diagnostic Agent + +Goal: +分析扫描失败原因并给出修复方案 +``` + +--- + +# 57. Scheduler + Event + +Scheduler 可以产生 Event: + +```text +Cron + ↓ +Scheduler + ↓ +Event + ↓ +Agent / Task / Plugin +``` + +也可以直接创建 Task。 + +两种都必须通过 Runtime。 + +--- + +# 58. Event Trigger Resource + +统一: + +```text +core.eventTrigger +``` + +支持: + +```text +Event → Action +Event → Task +Event → Agent +Event → Notification +Event → Webhook +``` + +--- + +# 59. Event Trigger Model + +```ts +export interface EventTrigger { + id: string + + name: string + + eventTypes: string[] + + filter?: EventFilter + + target: + | { + type: "action" + actionId: string + } + | { + type: "task" + taskType: string + } + | { + type: "agent" + agentProfileId: string + } + | { + type: "notification" + templateId: string + } + | { + type: "webhook" + subscriptionId: string + } + + enabled: boolean +} +``` + +--- + +# 60. Event Permission + +事件本身也是受权限控制的。 + +例如: + +```text +core.user.created +``` + +普通用户不能读取所有 User Events。 + +必须: + +```text +Event Permission ++ +Resource Permission ++ +Scope +``` + +--- + +# 61. Sensitive Event + +Event Payload 可能包含敏感数据。 + +例如: + +```text +password +token +API key +private URL +secret +``` + +禁止直接进入: + +```text +Event Store +Log +Realtime +Webhook +Notification +``` + +必须: + +```text +redact +mask +reference +``` + +--- + +# 62. Event Data Classification + +Event Payload 支持: + +```text +public +internal +sensitive +secret +``` + +推荐: + +```ts +export interface EventSecurityMetadata { + classification: + | "public" + | "internal" + | "sensitive" + | "secret" +} +``` + +--- + +# 63. Tenant Isolation + +Event 必须支持: + +```text +organizationId +projectId +environment +``` + +Event Query 必须自动注入 Scope。 + +例如: + +```text +User A + ↓ +query events + ↓ +organizationId = org_A +``` + +禁止客户端自己指定: + +```text +organizationId = org_B +``` + +覆盖服务端 Scope。 + +--- + +# 64. Event Retention + +不是所有 Event 永久保存。 + +支持: + +```text +retention policy +``` + +例如: + +```text +Audit Events: +365 days + +Task Events: +180 days + +Debug Events: +30 days + +Realtime-only: +not persisted +``` + +--- + +# 65. Event Archiving + +大规模 Event: + +```text +PostgreSQL + ↓ +Archive + ↓ +Object Storage +``` + +可以使用: + +```text +15_FILE_ARTIFACT_STORAGE_RUNTIME +``` + +保存: + +```text +event archive +``` + +--- + +# 66. Event Compaction + +部分高频事件不需要永久保存每一次。 + +例如: + +```text +task.progress +``` + +可能每秒产生多个事件。 + +Realtime 可以全部发送。 + +Event Store 可以: + +```text +sampling +aggregation +compaction +``` + +例如: + +```text +0% +1% +2% +3% +... +99% +``` + +长期存储只保留: + +```text +0% +25% +50% +75% +100% +``` + +但: + +> Audit / Security / Financial Events 不允许丢失。 + +--- + +# 67. Backpressure + +如果 Event Producer 很快: + +```text +10000 events/s +``` + +而 Consumer: + +```text +1000 events/s +``` + +必须产生 Backpressure。 + +策略: + +```text +queue +batch +concurrency +rate limit +priority +sampling +``` + +--- + +# 68. Event Priority + +```ts +export type EventPriority = + | "low" + | "normal" + | "high" + | "critical" +``` + +例如: + +```text +security.alert = critical + +task.progress = low +``` + +--- + +# 69. Event Batch + +支持: + +```ts +publishMany(events) +``` + +减少: + +```text +DB IO +Redis IO +Network IO +``` + +--- + +# 70. Event Transaction + +Action Runtime 中: + +```text +Action + ↓ +DB Transaction + ├── mutate data + └── append Outbox Event + ↓ +commit +``` + +Action 成功但 Event 不应该丢失。 + +--- + +# 71. Event Failure Isolation + +一个 Handler 失败: + +```text +Handler A ❌ +Handler B ✅ +Handler C ✅ +``` + +不能导致整个 Event 失败。 + +Event Delivery 必须独立: + +```text +Event + ├── Delivery A + ├── Delivery B + └── Delivery C +``` + +--- + +# 72. Event Delivery Resource + +```text +core.eventDelivery +``` + +```ts +export interface EventDelivery { + id: string + + eventId: string + + subscriptionId: string + + handlerId: string + + status: + | "pending" + | "running" + | "completed" + | "retrying" + | "failed" + + attempts: number + + startedAt?: Date + + completedAt?: Date + + lastError?: string +} +``` + +--- + +# 73. Observability + +Event Runtime 必须提供: + +```text +events published +events processed +events failed +events retried +events DLQ +handler latency +handler error rate +webhook delivery rate +notification delivery rate +realtime connections +realtime messages +``` + +--- + +# 74. Metrics + +至少: + +```text +devos_events_published_total + +devos_events_processed_total + +devos_events_failed_total + +devos_event_handler_duration_ms + +devos_event_queue_depth + +devos_event_dlq_total + +devos_webhook_delivery_total + +devos_webhook_failure_total + +devos_notification_sent_total + +devos_notification_failed_total + +devos_realtime_connections + +devos_realtime_messages_total +``` + +--- + +# 75. Logging + +Event Log: + +```text +eventId +eventType +eventVersion +organizationId +resourceId +correlationId +causationId +handlerId +deliveryId +duration +status +``` + +不要默认记录完整敏感 Payload。 + +--- + +# 76. Tracing + +推荐: + +```text +OpenTelemetry +``` + +Trace: + +```text +HTTP Request + ↓ +Action + ↓ +Execution + ↓ +Event Publish + ↓ +Event Delivery + ↓ +Handler + ↓ +Action +``` + +使用: + +```text +traceId +spanId +``` + +--- + +# 77. Database Model + +至少: + +```text +events + +event_outbox + +event_inbox + +event_subscriptions + +event_deliveries + +event_dead_letters + +event_triggers + +notifications + +notification_preferences + +notification_templates + +webhook_subscriptions + +webhook_deliveries +``` + +--- + +# 78. PostgreSQL Schema + +建议: + +```text +events +``` + +字段: + +```text +id +type +version +occurred_at +published_at +actor_type +actor_id +organization_id +project_id +environment +resource_type +resource_id +correlation_id +causation_id +request_id +execution_id +task_id +job_id +payload +metadata +created_at +``` + +索引: + +```text +(type, occurred_at) + +(organization_id, occurred_at) + +(resource_type, resource_id, occurred_at) + +(correlation_id) + +(task_id, occurred_at) + +(execution_id, occurred_at) +``` + +--- + +# 79. Redis + +Redis 用于: + +```text +Event Queue +Realtime Pub/Sub +Connection Coordination +Rate Limit +Locks +Short-lived Event State +``` + +不要把 Redis 作为唯一 Event Store。 + +数据库 / Durable Storage 才是长期事实来源。 + +--- + +# 80. Event Bus Provider + +DevOS 必须抽象: + +```ts +export interface EventBusProvider { + publish( + event: DevOSEvent + ): Promise + + consume( + consumer: EventConsumer + ): Promise +} +``` + +第一版可以: + +```text +Redis Streams +``` + +后续可以: + +```text +NATS +Kafka +RabbitMQ +``` + +不允许业务层依赖具体实现。 + +--- + +# 81. Recommended Initial Implementation + +第一阶段: + +```text +PostgreSQL ++ +Redis Streams ++ +WebSocket/SSE +``` + +架构: + +```text +PostgreSQL + ├── Event Store + ├── Outbox + ├── Inbox + └── Notification + +Redis + ├── Event Queue + ├── Realtime Pub/Sub + └── Distributed Coordination +``` + +--- + +# 82. Event Runtime API + +```ts +export interface EventRuntime { + publish( + input: PublishEventInput + ): Promise> + + publishMany( + input: PublishEventInput[] + ): Promise + + query( + input: EventQuery + ): Promise + + replay( + input: EventReplayInput + ): Promise + + subscribe( + input: SubscribeEventInput + ): Promise + + unsubscribe( + subscriptionId: string + ): Promise +} +``` + +--- + +# 83. Notification Runtime API + +```ts +export interface NotificationRuntime { + create( + input: CreateNotificationInput + ): Promise + + send( + notificationId: string + ): Promise + + markRead( + notificationId: string + ): Promise + + markAllRead( + recipientId: string + ): Promise + + list( + input: NotificationQuery + ): Promise +} +``` + +--- + +# 84. Realtime API + +```ts +export interface RealtimeRuntime { + publish( + channel: string, + message: RealtimeMessage + ): Promise + + authorize( + connection: RealtimeConnection, + channel: string + ): Promise + + subscribe( + connection: RealtimeConnection, + channel: string + ): Promise + + unsubscribe( + connection: RealtimeConnection, + channel: string + ): Promise +} +``` + +--- + +# 85. Generic Resource Events + +所有 Resource 默认可以产生: + +```text +resource.created +resource.updated +resource.deleted +``` + +但实际 Event Type 应该使用完整 namespace。 + +例如: + +```text +core.user.created +seo.website.created +core.task.updated +``` + +--- + +# 86. Generic Action Events + +Action Runtime 默认可以产生: + +```text +action.started +action.completed +action.failed +action.cancelled +``` + +建议具体化: + +```text +execution.started +execution.completed +execution.failed +execution.cancelled +``` + +--- + +# 87. Task Events + +Task Runtime 必须发布: + +```text +core.task.created +core.task.queued +core.task.started +core.task.progress +core.task.paused +core.task.resumed +core.task.waiting +core.task.completed +core.task.failed +core.task.cancelled +``` + +--- + +# 88. Job Events + +```text +core.job.created +core.job.queued +core.job.started +core.job.progress +core.job.retrying +core.job.completed +core.job.failed +core.job.cancelled +``` + +--- + +# 89. Execution Events + +```text +core.execution.started +core.execution.completed +core.execution.failed +core.execution.cancelled +``` + +--- + +# 90. Artifact Events + +来自: + +15_FILE_ARTIFACT_STORAGE_RUNTIME + +支持: + +```text +core.artifact.created +core.artifact.version.created +core.artifact.ready +core.artifact.deleted +``` + +--- + +# 91. File Events + +```text +core.file.created +core.file.uploaded +core.file.processing +core.file.ready +core.file.quarantined +core.file.failed +core.file.deleted +``` + +--- + +# 92. Search Events + +来自: + +14_DATA_QUERY_SEARCH_INDEX_RUNTIME + +例如: + +```text +core.searchIndex.created +core.searchIndex.rebuilding +core.searchIndex.ready +core.searchIndex.failed +``` + +以及: + +```text +resource.changed +``` + +触发: + +```text +Index Job +``` + +--- + +# 93. Cache Invalidation + +不要让 Plugin 自己调用 Redis 删除 Cache。 + +正确: + +```text +Action + ↓ +Resource Event + ↓ +Cache Handler + ↓ +Cache Runtime +``` + +--- + +# 94. Global Event Timeline + +DevOS UI 必须支持: + +```text +System +Organization +Project +Resource +Task +Agent +Plugin +``` + +统一 Timeline。 + +例如: + +```text +10:31 Agent started task +10:32 Website scan started +10:33 Website scan completed +10:33 17 issues found +10:34 Report artifact created +10:35 Task completed +``` + +数据来源: + +```text +Event Store +``` + +--- + +# 95. UI Realtime Architecture + +前端: + +```text +React + ↓ +Realtime Client + ↓ +WebSocket / SSE + ↓ +Realtime Runtime + ↓ +Event +``` + +建议提供: + +```text +packages/realtime-client +``` + +统一 API: + +```ts +const stream = realtime.subscribe( + "task:task_123" +) + +stream.on("message", handler) +``` + +--- + +# 96. Frontend Event Store + +前端可以使用: + +```text +Zustand ++ +TanStack Query +``` + +但是: + +> 前端 State 不是 Event Store。 + +Realtime Event 到达后: + +```text +Realtime + ↓ +Client Event Dispatcher + ├── invalidate Query + ├── update Zustand + └── show Notification +``` + +--- + +# 97. Query Invalidation + +例如: + +```text +core.task.completed +``` + +前端收到后: + +```text +invalidate: +["task", taskId] +``` + +以及: + +```text +["tasks"] +``` + +必要时刷新。 + +--- + +# 98. Optimistic UI + +可以: + +```text +Action + ↓ +optimistic update + ↓ +Event + ↓ +server authoritative state +``` + +服务器 Event / Query 结果最终拥有最高权威。 + +--- + +# 99. Connection Management + +Realtime Server 必须支持: + +```text +connect +authenticate +subscribe +unsubscribe +heartbeat +disconnect +reconnect +``` + +Connection: + +```ts +export interface RealtimeConnection { + id: string + + userId: string + + organizationId?: string + + connectedAt: Date + + metadata?: Record +} +``` + +--- + +# 100. Reconnect + +客户端断线后: + +```text +connect + ↓ +authenticate + ↓ +restore subscriptions + ↓ +resume stream +``` + +如果需要可靠恢复: + +```text +lastEventId +``` + +服务器可以: + +```text +replay missed events +``` + +--- + +# 101. Last Event ID + +SSE 必须支持: + +```text +Last-Event-ID +``` + +WebSocket 可以: + +```json +{ + "resumeFrom": "event_123" +} +``` + +Realtime Runtime 根据 Event Store 决定是否可以恢复。 + +--- + +# 102. Event Delivery Guarantees + +DevOS 明确声明: + +```text +Event Store: +Durable + +Event Queue: +At-Least-Once + +Handler: +At-Least-Once + +Webhook: +At-Least-Once + +Realtime: +Best Effort by default + +Notification: +At-Least-Once with deduplication +``` + +不要宣称: + +```text +Exactly Once +``` + +除非底层 Provider + Handler 真正保证。 + +--- + +# 103. Security + +必须防止: + +```text +Cross Tenant Event Leak +Cross Project Event Leak +Unauthorized Subscription +Webhook SSRF +Webhook Secret Leak +Event Payload Secret Leak +Realtime Channel Hijacking +Notification Spoofing +Replay Abuse +``` + +--- + +# 104. Webhook SSRF Protection + +Webhook URL 创建时必须检查: + +```text +localhost +127.0.0.1 +0.0.0.0 +private IP +link-local +metadata service +internal hostname +``` + +并支持: + +```text +DNS rebinding protection +IP validation +redirect restrictions +timeout +max response size +``` + +--- + +# 105. Event Payload Limits + +必须限制: + +```text +max event payload size +max metadata size +max notification body size +max webhook response size +max realtime message size +``` + +推荐默认: + +```text +Event payload: +256 KB + +Realtime: +64 KB + +Notification: +64 KB +``` + +具体值允许配置。 + +--- + +# 106. Large Payload + +如果 Event Payload 很大: + +不要: + +```json +{ + "payload": "10MB..." +} +``` + +应该: + +```json +{ + "artifactId": "artifact_123" +} +``` + +然后: + +```text +Artifact Runtime +``` + +读取。 + +--- + +# 107. Event Artifact Integration + +例如: + +```text +Agent generated report +``` + +Event: + +```json +{ + "type": "core.artifact.created", + "payload": { + "artifactId": "artifact_123" + } +} +``` + +而不是把整个报告塞进 Event。 + +--- + +# 108. Event Schema Registry + +Event 必须注册 Schema。 + +```ts +export interface EventSchema { + type: string + + version: number + + schema: unknown + + description?: string + + deprecated?: boolean + + breakingChanges?: string[] +} +``` + +Registry: + +```text +Event Schema Registry +``` + +用于: + +```text +validation +documentation +version compatibility +MCP discovery +Agent discovery +``` + +--- + +# 109. Plugin Event Schema + +Plugin 安装后注册: + +```text +Plugin + ├── Actions + ├── Resources + ├── Skills + ├── MCP + └── Events +``` + +Event 也进入: + +```text +Capability Registry +``` + +但 Event Capability 类型应与 Action Capability 区分。 + +--- + +# 110. Agent Event Capability + +Agent 可以发现: + +```text +event.subscribe +event.query +event.observe +``` + +但必须经过: + +```text +permission +scope +policy +``` + +--- + +# 111. Agent Event Trigger Example + +用户: + +```text +如果服务器宕机,就让 Agent 自动诊断。 +``` + +系统: + +```text +Event Trigger + ↓ +devops.server.down + ↓ +Agent Goal + ↓ +Agent Runtime + ↓ +Skill + ↓ +Action +``` + +Agent 不需要轮询服务器。 + +--- + +# 112. Event Driven Architecture + +DevOS 最终形成: + +```text +Action Driven ++ +Event Driven ++ +Task Driven ++ +Agent Driven +``` + +关系: + +```text +Action + ↓ +Event + ↓ +Task / Agent / Plugin / Notification +``` + +--- + +# 113. 不允许 Event 无限递归 + +例如: + +```text +A + ↓ +B + ↓ +C + ↓ +A +``` + +必须支持: + +```text +max event depth +``` + +Event Metadata: + +```ts +{ + eventDepth: 3 +} +``` + +超过限制: + +```text +reject / DLQ +``` + +--- + +# 114. Event Loop Detection + +使用: + +```text +causationId +correlationId +event chain +``` + +检测: + +```text +same event type +same resource +same handler +``` + +短时间重复触发。 + +必要时: + +```text +circuit breaker +``` + +--- + +# 115. Handler Concurrency + +Handler 可以定义: + +```ts +concurrency: 10 +``` + +但是资源敏感 Handler: + +```text +concurrency = 1 +``` + +例如: + +```text +production deployment +``` + +--- + +# 116. Handler Timeout + +每个 Handler: + +```text +timeout +``` + +例如: + +```text +30s +5m +``` + +超时: + +```text +AbortSignal + ↓ +retry +``` + +--- + +# 117. Handler Transaction + +如果 Handler 修改多个 DB 表: + +```text +Action Runtime + ↓ +Transaction +``` + +不要自己创建不可控 Transaction。 + +--- + +# 118. Event Consumer Groups + +支持: + +```text +consumer group +``` + +例如: + +```text +search-indexer +notification-service +webhook-service +analytics-service +``` + +同一个 Event: + +```text +Event + ├── search-indexer + ├── notification-service + ├── webhook-service + └── analytics-service +``` + +每个 Consumer Group 独立消费。 + +--- + +# 119. Event Priority Queues + +推荐: + +```text +critical +high +normal +low +``` + +例如: + +```text +security.alert → critical + +task.completed → normal + +task.progress → low +``` + +--- + +# 120. Batch Processing + +Consumer 可以: + +```text +1 event +``` + +也可以: + +```text +100 events +``` + +例如 Search Index: + +```text +100 Resource Events + ↓ +one index batch +``` + +--- + +# 121. Notification Deduplication + +避免: + +```text +same event + ↓ +same notification + ↓ +duplicate +``` + +使用: + +```text +deduplicationKey +``` + +例如: + +```text +taskId + eventType +``` + +--- + +# 122. Notification Aggregation + +高频通知: + +```text +100 task progress events +``` + +不应该: + +```text +100 emails +``` + +支持聚合: + +```text +You have 37 task updates. +``` + +--- + +# 123. Email Queue + +Email 不允许在 HTTP Request 中直接发送。 + +必须: + +```text +Notification + ↓ +Task / Job + ↓ +Queue + ↓ +Worker + ↓ +Email Provider +``` + +--- + +# 124. Notification Provider + +抽象: + +```ts +export interface NotificationProvider { + send( + message: NotificationMessage + ): Promise +} +``` + +未来: + +```text +SMTP +SES +SendGrid +Resend +Slack +Discord +Telegram +``` + +都只是 Provider。 + +--- + +# 125. Realtime Provider + +抽象: + +```ts +export interface RealtimeProvider { + publish( + channel: string, + message: RealtimeMessage + ): Promise +} +``` + +第一版: + +```text +Redis Pub/Sub ++ +WebSocket ++ +SSE +``` + +--- + +# 126. API + +至少提供: + +```text +GET /api/events +GET /api/events/:id + +POST /api/events/replay + +GET /api/event-subscriptions +POST /api/event-subscriptions +PATCH /api/event-subscriptions/:id +DELETE /api/event-subscriptions/:id + +GET /api/notifications +POST /api/notifications/:id/read +POST /api/notifications/read-all + +GET /api/webhooks +POST /api/webhooks +PATCH /api/webhooks/:id +DELETE /api/webhooks/:id + +GET /api/tasks/:id/events +GET /api/tasks/:id/stream + +GET /api/agent-runs/:id/stream +``` + +--- + +# 127. WebSocket API + +例如: + +```text +/ws +``` + +客户端: + +```json +{ + "type": "subscribe", + "channel": "task:task_123" +} +``` + +服务端: + +```json +{ + "type": "subscribed", + "channel": "task:task_123" +} +``` + +事件: + +```json +{ + "type": "task.progress", + "channel": "task:task_123", + "payload": { + "progress": 65 + } +} +``` + +--- + +# 128. SSE API + +例如: + +```text +GET /api/tasks/task_123/stream +``` + +返回: + +```text +event: task.started +data: {...} + +event: task.progress +data: {...} + +event: task.completed +data: {...} +``` + +--- + +# 129. CLI + +必须提供: + +```bash +devos events list + +devos events get + +devos events replay + +devos events replay --type core.task.completed + +devos events subscriptions + +devos events dlq + +devos events dlq retry + +devos notifications list + +devos webhooks list + +devos webhooks test +``` + +--- + +# 130. Admin UI + +必须提供: + +```text +System + ├── Events + │ ├── Event Explorer + │ ├── Event Detail + │ ├── Event Replay + │ ├── Subscriptions + │ ├── Deliveries + │ └── Dead Letter Queue + │ + ├── Notifications + │ ├── Templates + │ ├── Rules + │ ├── Preferences + │ └── Delivery Logs + │ + ├── Webhooks + │ ├── Subscriptions + │ ├── Deliveries + │ └── Logs + │ + └── Realtime + ├── Connections + └── Channels +``` + +--- + +# 131. Event Explorer + +支持: + +```text +Event Type +Version +Organization +Project +Resource +Actor +Task +Job +Execution +Correlation ID +Date Range +Status +``` + +结果: + +```text +Timeline +``` + +--- + +# 132. Event Detail + +必须显示: + +```text +Event ID +Type +Version +Occurred At +Actor +Resource +Organization +Project +Correlation +Causation +Payload +Metadata +Deliveries +``` + +敏感字段必须隐藏。 + +--- + +# 133. Event Delivery UI + +例如: + +```text +Event: +core.task.completed + +Deliveries: + +Notification completed +Webhook #1 completed +Search Index completed +Analytics failed → retrying +``` + +--- + +# 134. DLQ UI + +支持: + +```text +inspect +retry +bulk retry +discard +filter +``` + +必须显示: + +```text +event +handler +attempts +error +last attempt +``` + +--- + +# 135. Plugin Developer API + +Plugin 可以: + +```ts +devos.events.publish(...) +devos.events.subscribe(...) +devos.notifications.create(...) +devos.realtime.publish(...) +``` + +但是这些 API 最终进入: + +```text +Event Runtime +Notification Runtime +Realtime Runtime +``` + +不能访问: + +```text +Redis +PostgreSQL +WebSocket Server +``` + +--- + +# 136. SDK + +推荐: + +```text +packages/events +packages/notifications +packages/realtime +packages/webhooks +``` + +例如: + +```ts +import { + eventRuntime +} from "@devos/events" +``` + +--- + +# 137. Package Structure + +最终: + +```text +packages/ +├── event/ +│ ├── core/ +│ ├── runtime/ +│ ├── bus/ +│ ├── store/ +│ ├── outbox/ +│ ├── inbox/ +│ ├── subscription/ +│ ├── delivery/ +│ ├── replay/ +│ └── schema/ +│ +├── notification/ +│ ├── core/ +│ ├── runtime/ +│ ├── template/ +│ ├── preference/ +│ └── providers/ +│ +├── realtime/ +│ ├── core/ +│ ├── runtime/ +│ ├── websocket/ +│ ├── sse/ +│ └── client/ +│ +└── webhook/ + ├── core/ + ├── runtime/ + ├── delivery/ + └── security/ +``` + +--- + +# 138. NestJS Backend Modules + +建议: + +```text +EventModule + +NotificationModule + +RealtimeModule + +WebhookModule +``` + +依赖: + +```text +EventModule + ↓ +TaskModule +ActionModule +PluginModule +AgentModule +SearchModule +StorageModule +``` + +注意不要形成循环依赖。 + +--- + +# 139. Dependency Rule + +推荐依赖方向: + +```text +Core Runtime + ↑ +Event Runtime + ↑ +Feature Modules +``` + +Feature Module: + +```text +can publish Event +can subscribe Event +``` + +但 Event Runtime: + +```text +must not import SEO +must not import CRM +must not import DevOps +``` + +--- + +# 140. Event Registry + +统一: + +```ts +export interface EventRegistry { + register( + schema: EventSchema + ): void + + get( + type: string, + version: number + ): EventSchema | undefined + + list(): EventSchema[] +} +``` + +Plugin 安装时自动注册。 + +--- + +# 141. Event Validation + +Publish: + +```text +Event + ↓ +Registry + ↓ +Schema Validation + ↓ +Security Validation + ↓ +Outbox +``` + +非法 Event: + +```text +reject +``` + +--- + +# 142. Event Compatibility + +参考: + +12_MIGRATION_VERSIONING_COMPATIBILITY.md + +Event Schema 必须检查: + +```text +backward compatibility +forward compatibility +breaking change +deprecated fields +``` + +--- + +# 143. Deprecated Event + +Event 可以: + +```ts +deprecated: true +``` + +但不能立即删除。 + +流程: + +```text +v1 + ↓ +deprecated + ↓ +v2 + ↓ +migration period + ↓ +remove +``` + +--- + +# 144. Event Contract Test + +每个 Plugin Event 必须有: + +```text +schema test +publish test +subscription test +permission test +version test +replay test +``` + +--- + +# 145. Integration with Task Runtime + +Task Runtime: + +```text +Task created + ↓ +Event + ↓ +Realtime + ↓ +UI +``` + +Worker: + +```text +Job started + ↓ +Event + ↓ +Realtime +``` + +不要: + +```text +TaskService + ↓ +WebSocket +``` + +--- + +# 146. Integration with Agent Runtime + +Agent: + +```text +Goal + ↓ +Agent Run + ↓ +Task + ↓ +Event + ↓ +Observation + ↓ +Agent +``` + +Agent 不应该轮询: + +```text +SELECT task WHERE status = ... +``` + +而应该: + +```text +subscribe / observe Event +``` + +--- + +# 147. Integration with Search Runtime + +```text +Resource changed + ↓ +Event + ↓ +Search Index Handler + ↓ +Index Job + ↓ +Worker +``` + +数据库是 Source of Truth。 + +--- + +# 148. Integration with Storage Runtime + +```text +File uploaded + ↓ +file.uploaded + ↓ +Processing Task + ↓ +Artifact + ↓ +Event +``` + +--- + +# 149. Integration with Plugin Runtime + +Plugin 生命周期: + +```text +plugin.install +plugin.installed + +plugin.enable +plugin.enabled + +plugin.disable +plugin.disabled + +plugin.upgrade +plugin.upgraded + +plugin.uninstall +plugin.uninstalled +``` + +--- + +# 150. Integration with Migration Runtime + +Migration: + +```text +migration.started +migration.progress +migration.completed +migration.failed +``` + +可以实时显示: + +```text +Upgrade UI +``` + +--- + +# 151. Integration with Scheduler + +Scheduler: + +```text +schedule.triggered +``` + +然后: + +```text +Event + ↓ +Task / Agent +``` + +--- + +# 152. Event-Driven UI + +UI 中任何需要实时状态的模块都必须优先考虑: + +```text +Event + Query +``` + +而不是: + +```text +setInterval(fetch, 1000) +``` + +例如: + +```text +Task Progress +Job Progress +Agent Run +Deployment +File Processing +Plugin Upgrade +Migration +``` + +--- + +# 153. Polling Fallback + +如果客户端不支持 WebSocket/SSE: + +```text +Realtime unavailable + ↓ +fallback polling +``` + +但是: + +> Polling 是 fallback,不是主架构。 + +--- + +# 154. Offline / Reconnect + +客户端必须处理: + +```text +connection lost +reconnecting +resubscribing +event gap +``` + +状态: + +```text +connected +reconnecting +disconnected +``` + +--- + +# 155. Event Gap + +如果客户端发现: + +```text +event_100 +event_105 +``` + +中间缺失: + +```text +event_101-104 +``` + +可以: + +```text +GET /api/events?after=event_100 +``` + +重新同步。 + +--- + +# 156. Reliable UI State + +Realtime 只是: + +```text +notification / update signal +``` + +最终数据: + +```text +Query Runtime +``` + +例如: + +```text +task.completed + ↓ +invalidate task query + ↓ +GET task + ↓ +authoritative state +``` + +不要完全依赖客户端 Event Payload 作为最终状态。 + +--- + +# 157. Event Storm Protection + +如果一个资源: + +```text +每秒 10000 updates +``` + +系统必须支持: + +```text +coalescing +debounce +sampling +aggregation +``` + +尤其: + +```text +progress events +metrics +logs +``` + +--- + +# 158. Event Coalescing + +例如: + +```text +task.progress 1 +task.progress 2 +task.progress 3 +... +``` + +Realtime 可以合并: + +```text +task.progress = 3 +``` + +但: + +```text +security.alert +payment.completed +deployment.failed +``` + +禁止合并。 + +--- + +# 159. Event Categories + +可以定义: + +```ts +export type EventCategory = + | "audit" + | "domain" + | "system" + | "integration" + | "progress" + | "debug" +``` + +不同 Category: + +```text +retention +priority +storage +delivery +``` + +策略不同。 + +--- + +# 160. Event Governance + +系统管理员可以查看: + +```text +Event Types +Schemas +Consumers +Handlers +Subscriptions +Failure Rate +Retention +``` + +Plugin 开发者只能管理: + +```text +own namespace +``` + +--- + +# 161. Namespace Isolation + +Plugin: + +```text +seo +``` + +只能注册: + +```text +seo.* +``` + +不能覆盖: + +```text +core.* +``` + +除非系统明确授权。 + +--- + +# 162. Event Ownership + +Schema: + +```ts +owner: string +``` + +例如: + +```text +core.task.completed +owner = devos-core + +seo.website.scanned +owner = seo-plugin +``` + +--- + +# 163. Event Documentation + +每个 Event 自动生成: + +```text +Event Type +Description +Version +Schema +Producer +Consumers +Permissions +Retention +``` + +可以作为: + +```text +Developer Portal +MCP Discovery +Agent Capability Discovery +``` + +--- + +# 164. Agent-Friendly Event Description + +Agent 不需要接收完整所有 Event。 + +Capability Discovery: + +```text +Level 1: +event type + description + +Level 2: +schema + +Level 3: +subscription instructions +``` + +继续遵守: + +```text +06_MCP_SKILL_AGENT_RUNTIME.md +``` + +的 Progressive Disclosure。 + +--- + +# 165. Event Search + +使用: + +14_DATA_QUERY_SEARCH_INDEX_RUNTIME + +支持: + +```text +keyword +event type +resource +actor +task +correlation +``` + +但: + +> Event Store 是事实来源,Search Index 只是加速查询。 + +--- + +# 166. Event Audit + +Audit Event 不允许被普通用户删除。 + +例如: + +```text +user.login +permission.changed +role.changed +api_key.created +plugin.installed +deployment.started +``` + +Audit Event: + +```text +immutable +``` + +--- + +# 167. Event Immutability + +Event 一旦写入: + +```text +不可修改 +``` + +如果发现错误: + +```text +publish correction event +``` + +例如: + +```text +billing.payment.created +billing.payment.corrected +``` + +而不是修改原 Event。 + +--- + +# 168. Event Integrity + +关键 Event 可以保存: + +```text +checksum +``` + +例如: + +```text +SHA-256 +``` + +用于: + +```text +audit integrity +archive verification +``` + +--- + +# 169. Event Encryption + +敏感 Event Payload: + +```text +encryption at rest +``` + +Secret 类型: + +```text +不要进入 Event Payload +``` + +优先保存: + +```text +secret reference +``` + +--- + +# 170. Multi-Instance Realtime + +DevOS 多实例: + +```text +Browser + ↓ +Instance A +``` + +Event: + +```text +Instance B +``` + +必须: + +```text +Redis Pub/Sub +``` + +广播: + +```text +Instance B + ↓ +Redis + ↓ +Instance A + ↓ +Browser +``` + +--- + +# 171. Horizontal Scaling + +Event Worker: + +```text +Worker 1 +Worker 2 +Worker 3 +``` + +使用: + +```text +consumer group +partition +lease +``` + +保证: + +```text +same partition +ordered +``` + +--- + +# 172. Realtime Scaling + +Realtime: + +```text +WebSocket Server 1 +WebSocket Server 2 +WebSocket Server 3 +``` + +共享: + +```text +Redis +``` + +--- + +# 173. Health Checks + +必须: + +```text +GET /health/events + +GET /health/realtime + +GET /health/webhooks + +GET /health/notifications +``` + +检查: + +```text +DB +Redis +Queue +Worker +Provider +``` + +--- + +# 174. Graceful Shutdown + +关闭: + +```text +stop accepting new events + ↓ +drain consumers + ↓ +close realtime connections + ↓ +flush buffers + ↓ +shutdown +``` + +--- + +# 175. Event Runtime Configuration + +配置: + +```text +EVENT_BUS_PROVIDER +EVENT_MAX_PAYLOAD_SIZE +EVENT_RETENTION +EVENT_RETRY_POLICY + +REALTIME_PROVIDER +REALTIME_MAX_CONNECTIONS +REALTIME_MESSAGE_LIMIT + +WEBHOOK_TIMEOUT +WEBHOOK_MAX_RETRIES + +NOTIFICATION_PROVIDER +NOTIFICATION_BATCH_SIZE +``` + +--- + +# 176. Testing + +必须实现: + +## Unit Tests + +```text +Event Envelope +Event Schema +Event Registry +Filter +Subscription +Retry +Idempotency +Replay +Notification +Webhook Signature +Realtime Channel Authorization +``` + +--- + +# 177. Integration Tests + +至少: + +```text +Action + ↓ +Execution + ↓ +Event + ↓ +Handler +``` + +验证完整链路。 + +--- + +# 178. Outbox Test + +测试: + +```text +DB success +Outbox success +Event published +``` + +以及: + +```text +DB success +Outbox worker crash + ↓ +restart + ↓ +event eventually published +``` + +--- + +# 179. Inbox Test + +重复 Event: + +```text +event_123 +event_123 +event_123 +``` + +Handler 最终: + +```text +execute once +``` + +--- + +# 180. Retry Test + +模拟: + +```text +handler fails 2 times +success on third +``` + +验证: + +```text +attempts = 3 +``` + +--- + +# 181. DLQ Test + +模拟: + +```text +all retries failed +``` + +验证: + +```text +DLQ record created +``` + +然后: + +```text +retry DLQ +``` + +必须可以恢复。 + +--- + +# 182. Replay Test + +```text +Event Store + ↓ +Replay + ↓ +selected handler +``` + +验证: + +```text +non-replay-safe handler +``` + +不能执行。 + +--- + +# 183. Permission Test + +User A: + +```text +org_A +``` + +不能: + +```text +subscribe org_B event +``` + +验证: + +```text +403 +``` + +--- + +# 184. Webhook Security Test + +验证: + +```text +valid signature +invalid signature +expired timestamp +replay request +private IP +redirect +timeout +``` + +--- + +# 185. Realtime Test + +验证: + +```text +connect +authenticate +subscribe +publish +receive +unsubscribe +reconnect +resume +``` + +--- + +# 186. Agent Integration Test + +测试: + +```text +Event + ↓ +Agent Trigger + ↓ +Goal + ↓ +Agent Run + ↓ +Task + ↓ +Action + ↓ +Event +``` + +必须完整通过。 + +--- + +# 187. Plugin Integration Test + +Plugin 安装: + +```text +Plugin + ↓ +Event Schema + ↓ +Event Subscription + ↓ +Handler +``` + +卸载: + +```text +subscription removed +handler removed +``` + +历史 Event 不删除。 + +--- + +# 188. Performance Requirements + +第一阶段目标: + +```text +Event publish p95 < 100ms + +Event handler scheduling p95 < 200ms + +Realtime publish p95 < 100ms + +Notification enqueue p95 < 200ms +``` + +这些是初始工程目标,允许根据实际部署调整。 + +--- + +# 189. Reliability Requirements + +目标: + +```text +No event loss after committed transaction + +At-least-once delivery + +Retry recovery + +DLQ recovery + +Realtime reconnect + +Webhook retry +``` + +--- + +# 190. Zcode Implementation Rules + +Zcode 必须严格遵守: + +### Rule 1 + +禁止 Plugin 自己创建: + +```text +Event Bus +WebSocket Server +Notification Service +Webhook Queue +``` + +必须使用: + +```text +DevOS Runtime +``` + +--- + +### Rule 2 + +禁止: + +```text +Action → Email +Action → WebSocket +Action → Webhook +``` + +正确: + +```text +Action + ↓ +Event + ↓ +Notification / Realtime / Webhook +``` + +--- + +### Rule 3 + +禁止 Handler 绕过: + +```text +Action Runtime +``` + +--- + +### Rule 4 + +Event 必须: + +```text +versioned +immutable +traceable +tenant-aware +permission-aware +``` + +--- + +### Rule 5 + +默认: + +```text +At-Least-Once +``` + +所有 Consumer 必须考虑: + +```text +idempotency +``` + +--- + +### Rule 6 + +Event Store 与 Realtime 必须分离。 + +```text +Event Store = durable fact + +Realtime = delivery mechanism +``` + +--- + +### Rule 7 + +Realtime 不是最终数据来源。 + +UI 收到 Event 后: + +```text +invalidate Query +``` + +必要时重新 Query。 + +--- + +### Rule 8 + +Agent 不能直接访问: + +```text +Event DB +Redis +WebSocket +Webhook +Notification Provider +``` + +必须通过: + +```text +Capability / Runtime +``` + +--- + +### Rule 9 + +MCP 不允许绕过: + +```text +Event Runtime +Action Runtime +Permission +Scope +Audit +``` + +--- + +### Rule 10 + +所有 Event 都必须包含: + +```text +eventId +type +version +occurredAt +actor +correlationId +``` + +适用时还必须包含: + +```text +causationId +requestId +executionId +taskId +jobId +resource +``` + +--- + +### Rule 11 + +大 Payload 不允许直接放 Event。 + +使用: + +```text +Artifact +File +Resource Reference +``` + +--- + +### Rule 12 + +高频 Progress Event 必须支持: + +```text +coalescing +sampling +aggregation +``` + +--- + +### Rule 13 + +Event Handler 必须独立失败。 + +```text +Handler A failed +``` + +不能影响: + +```text +Handler B +Handler C +``` + +--- + +### Rule 14 + +Webhook 必须具备: + +```text +HMAC Signature +Replay Protection +SSRF Protection +Timeout +Retry +``` + +--- + +### Rule 15 + +Realtime Channel 必须进行: + +```text +Authentication +Authorization +Tenant Scope +Resource Scope +``` + +--- + +# 191. Acceptance Criteria + +本模块完成必须满足: + +```text +[ ] Event Envelope +[ ] Event Schema Registry +[ ] Event Registry +[ ] Event Store +[ ] Event Bus +[ ] Outbox +[ ] Inbox +[ ] Subscription +[ ] Event Handler +[ ] Event Delivery +[ ] Retry +[ ] DLQ +[ ] Replay +[ ] Event Filter +[ ] Event Permission +[ ] Tenant Isolation +[ ] Event Ordering +[ ] Event Partition +[ ] Event Retention +[ ] Event Observability + +[ ] Notification Runtime +[ ] Notification Template +[ ] Notification Preference +[ ] In-App Notification +[ ] Email Queue +[ ] Notification Deduplication +[ ] Notification Aggregation + +[ ] Webhook Runtime +[ ] Webhook Subscription +[ ] Webhook Delivery +[ ] HMAC Signature +[ ] Webhook Retry +[ ] SSRF Protection + +[ ] Realtime Runtime +[ ] WebSocket +[ ] SSE +[ ] Channel Authorization +[ ] Reconnect +[ ] Last Event ID +[ ] Event Gap Recovery +[ ] Horizontal Scaling + +[ ] Task Streaming +[ ] Job Streaming +[ ] Execution Streaming +[ ] Agent Streaming +[ ] Migration Streaming +[ ] Plugin Streaming + +[ ] Plugin Event Integration +[ ] MCP Event Integration +[ ] Agent Event Trigger +[ ] Scheduler Event Trigger +[ ] Search Integration +[ ] Storage Integration +[ ] Task Integration + +[ ] Event Explorer +[ ] Event Timeline +[ ] Notification Center +[ ] Webhook Dashboard +[ ] DLQ UI +[ ] Realtime Connection UI + +[ ] CLI +[ ] API +[ ] Unit Tests +[ ] Integration Tests +[ ] Security Tests +[ ] Performance Tests +``` + +--- + +# 192. Final Architecture + +完成本模块后,DevOS 的整体 Runtime 应该变成: + +```text + ┌───────────────┐ + │ User │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ Goal │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ Agent Runtime │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ Task │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ Job │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ Action │ + └───────┬───────┘ + │ + ▼ + ┌─────────────────────┐ + │ Action Runtime │ + └──────────┬──────────┘ + │ + ▼ + ┌─────────────────────┐ + │ Execution │ + └──────────┬──────────┘ + │ + ▼ + ┌─────────────────────┐ + │ Event Runtime │ + └──────────┬──────────┘ + │ + ┌─────────────────────────┼─────────────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ + │ Event Store │ │ Event Queue │ │ Outbox │ + └──────────────┘ └──────┬───────┘ └──────────────┘ + │ + ┌───────────────┼────────────────┐ + │ │ │ + ▼ ▼ ▼ + Handlers Notifications Webhook + │ │ │ + ▼ ▼ ▼ + Actions In-App/Email External Apps + │ + ▼ + Realtime + │ + ┌─────┴─────┐ + ▼ ▼ + WebSocket SSE + │ │ + └─────┬─────┘ + ▼ + DevOS UI +``` + +--- + +# 193. Final Golden Rule + +DevOS 的事件体系最终必须遵守: + +```text +ACTION + ↓ +EXECUTION + ↓ +EVENT + ↓ +EVENT RUNTIME + ↓ +┌───────────┬────────────┬────────────┬────────────┐ +│ │ │ │ +▼ ▼ ▼ ▼ +TASK AGENT NOTIFICATION WEBHOOK +│ │ │ │ +▼ ▼ ▼ ▼ +JOB OBSERVE IN-APP/EMAIL EXTERNAL +│ +▼ +REALTIME +│ +├── WebSocket +└── SSE +``` + +最终原则: + +> **Event 是系统事实,Action 是系统行为,Task 是工作,Agent 是决策,Notification 是通知,Realtime 是传输,Webhook 是外部集成。** + +> **所有这些能力必须建立在同一个 Event Runtime 之上,任何 Plugin、MCP、Agent、Task、UI 都不得自行建立第二套事件、通知或实时系统。** + +--- + +# 194. Zcode 最终检查 + +实现完成后,必须能够回答: + +```text +一个 Action 执行成功后,Event 在哪里产生? +Event 如何保证不会丢? +Event 如何 Retry? +Event 如何保证 Consumer 幂等? +Event 如何进入 Notification? +Event 如何进入 Webhook? +Event 如何实时推送给 UI? +Agent 如何观察 Event? +Plugin 如何订阅 Event? +MCP 如何访问 Event? +Event 如何 Replay? +Event 如何做权限控制? +Event 如何做 Tenant Isolation? +Event 如何追踪 Correlation? +Event 如何与 Task / Job / Execution 关联? +Realtime 断线后如何恢复? +Webhook 如何防 SSRF? +高频 Progress Event 如何防 Event Storm? +``` + +如果上述问题全部可以通过 DevOS Runtime 回答,而不是某个 Plugin 自己实现一套机制,则 **16_EVENT_STREAMING_NOTIFICATION_REALTIME_RUNTIME.md 达标**。 diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 441ec03..04e7c73 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -40,6 +40,7 @@ import { NoteModule } from "./modules/note/note.module"; import { CertificateModule } from "./modules/certificate/certificate.module"; import { GitModule } from "./modules/git/git.module"; import { SearchModule } from "./modules/search/search.module"; +import { V2Module } from "./v2/v2.module"; @Module({ imports: [ @@ -71,6 +72,7 @@ import { SearchModule } from "./modules/search/search.module"; CertificateModule, GitModule, SearchModule, + V2Module, ], controllers: [SystemController], providers: [ diff --git a/apps/api/src/v2/adapters/legacy-bridge.ts b/apps/api/src/v2/adapters/legacy-bridge.ts new file mode 100644 index 0000000..b26e12c --- /dev/null +++ b/apps/api/src/v2/adapters/legacy-bridge.ts @@ -0,0 +1,460 @@ +/** + * # v2 遗留功能桥接(docs 03 §44/§103) + * 把 v1 模块服务注册为 v2 Resource/Action(devops.* 命名空间)。 + * 这是"六入口一实现"的第一步:REST/MCP/Agent 逐步迁移到 Action Runtime。 + * 业务实现完全复用 v1 service(含审计/事件),Action 层只做契约与编排。 + */ +import { Injectable, OnModuleInit } from "@nestjs/common"; +import type { ActionContext } from "../foundation/types"; +import { z } from "zod"; +import { actionRegistry, defineAction, type ActionDefinition } from "../registry/action-registry"; +import { resourceRegistry } from "../registry/resource-registry"; +import { ServerService } from "../../modules/server/server.service"; +import { WebsiteService } from "../../modules/website/website.service"; +import { DeploymentService } from "../../modules/deployment/deployment.service"; +import { TaskService } from "../../modules/task/task.service"; +import { NoteService } from "../../modules/note/note.service"; +import { DomainService } from "../../modules/domain/domain.service"; +import { ContainerService } from "../../modules/container/container.service"; +import { MonitoringService } from "../../modules/monitoring/monitoring.service"; +import { AutomationService } from "../../modules/automation/automation.service"; +import { CredentialService } from "../../modules/credential/credential.service"; +import { JobQueueService } from "../../modules/job/job-queue.service"; + +/** # 注册上下文:workspace 感知的动作执行器包装 **/ +type WorkspaceAction = { + id: string; + resource: string; + name: string; + description: string; + mode?: "sync" | "async"; + permission?: string; + dangerous?: boolean; + visibility?: "public" | "internal" | "agent" | "admin"; + inputSchema?: z.ZodType; + outputSchema?: z.ZodType; + /** # 业务执行:ctx.workspaceId 已由 runtime 注入 actor/organization **/ + run: (workspaceId: string, input: TInput) => Promise; +}; + +@Injectable() +export class LegacyBridgeService implements OnModuleInit { + constructor( + private readonly servers: ServerService, + private readonly websites: WebsiteService, + private readonly deployments: DeploymentService, + private readonly tasks: TaskService, + private readonly notes: NoteService, + private readonly domains: DomainService, + private readonly containers: ContainerService, + private readonly monitoring: MonitoringService, + private readonly automations: AutomationService, + private readonly credentials: CredentialService, + private readonly jobs: JobQueueService, + ) {} + + /** # 模块初始化:注册全部 devops.* 资源与动作 */ + onModuleInit(): void { + this.registerResources(); + this.registerServerActions(); + this.registerWebsiteActions(); + this.registerDeploymentActions(); + this.registerTaskActions(); + this.registerNoteActions(); + this.registerDomainActions(); + this.registerContainerActions(); + this.registerMonitorActions(); + this.registerAutomationActions(); + this.registerJobActions(); + } + + /** # 注册资源类型(schema 元数据) */ + private registerResources(): void { + resourceRegistry.register({ + type: "devops.server", + label: "Server", + description: "Managed compute target reachable via SSH or local docker socket", + actionIds: ["devops.server.list", "devops.server.get", "devops.server.create", "devops.server.delete", "devops.server.connect", "devops.server.exec"], + ownership: { organization: true }, + ui: { icon: "CloudServerOutlined", listColumns: ["name", "host", "status"] }, + }); + resourceRegistry.register({ + type: "devops.website", + label: "Website", + description: "Deployable application bound to server/repository/domain", + actionIds: ["devops.website.list", "devops.website.get", "devops.website.create", "devops.website.update", "devops.website.delete", "devops.website.deploy", "devops.website.health", "devops.website.logs"], + ownership: { organization: true }, + ui: { icon: "GlobalOutlined", listColumns: ["name", "primaryDomain", "status"] }, + }); + resourceRegistry.register({ + type: "devops.deployment", + label: "Deployment", + actionIds: ["devops.deployment.list", "devops.deployment.get", "devops.deployment.create", "devops.deployment.cancel"], + ownership: { organization: true }, + ui: { icon: "ThunderboltOutlined", listColumns: ["id", "status", "progress"] }, + }); + resourceRegistry.register({ + type: "core.task", + label: "Task", + actionIds: ["core.task.list", "core.task.get", "core.task.create", "core.task.update", "core.task.delete"], + ownership: { organization: true }, + ui: { icon: "CheckSquareOutlined", listColumns: ["title", "status", "priority"] }, + }); + resourceRegistry.register({ + type: "core.note", + label: "Note", + actionIds: ["core.note.list", "core.note.get", "core.note.create", "core.note.update", "core.note.delete"], + ownership: { organization: true }, + ui: { icon: "ReadOutlined", listColumns: ["title", "tags", "updatedAt"] }, + }); + resourceRegistry.register({ + type: "devops.domain", + label: "Domain", + actionIds: ["devops.domain.list", "devops.domain.get", "devops.domain.create", "devops.domain.delete", "devops.domain.records", "devops.domain.upsertRecord"], + ownership: { organization: true }, + ui: { icon: "HddOutlined", listColumns: ["name", "provider", "status"] }, + }); + resourceRegistry.register({ + type: "devops.container", + label: "Container", + actionIds: ["devops.container.list", "devops.container.logs", "devops.container.stats", "devops.container.restart"], + ownership: { organization: true }, + ui: { icon: "DeploymentUnitOutlined", listColumns: ["name", "image", "state"] }, + }); + resourceRegistry.register({ + type: "devops.monitor", + label: "Monitor", + actionIds: ["devops.monitor.list", "devops.monitor.create", "devops.monitor.delete"], + ownership: { organization: true }, + ui: { icon: "AlertOutlined", listColumns: ["name", "target", "lastStatus"] }, + }); + resourceRegistry.register({ + type: "core.credential", + label: "Credential", + actionIds: ["core.credential.list", "core.credential.create", "core.credential.delete"], + ownership: { organization: true }, + ui: { icon: "KeyOutlined", listColumns: ["name", "type", "provider"] }, + }); + } + + /** # 注册单个动作的通用包装 */ + private register(def: WorkspaceAction): void { + actionRegistry.register( + { + ...def, + execute: async (ctx: ActionContext, input: unknown) => + def.run(ctx.organizationId ?? "", input as TInput), + } as unknown as ActionDefinition, + "legacy-bridge", + ); + } + + /** # devops.server.* */ + private registerServerActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "devops.server.list", resource: "devops.server", name: "List servers", + description: "List all servers in the workspace", inputSchema: z.object({}), + run: (wid) => this.servers.list(wid), + }); + this.register({ + id: "devops.server.get", resource: "devops.server", name: "Get server", + description: "Get a server by id", inputSchema: Ids, + run: (wid, i) => this.servers.get(wid, i.id), + }); + this.register({ + id: "devops.server.create", resource: "devops.server", name: "Create server", + description: "Register a new server (SSH or local docker)", + inputSchema: z.object({ name: z.string(), host: z.string(), port: z.number().optional(), username: z.string(), provider: z.enum(["ssh", "local"]).optional(), authType: z.enum(["PASSWORD", "SSH_KEY"]).optional(), password: z.string().optional(), privateKey: z.string().optional(), credentialId: z.string().optional() }), + run: (wid, i) => this.servers.create(wid, i as never), + }); + this.register({ + id: "devops.server.delete", resource: "devops.server", name: "Delete server", + description: "Delete a server", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.servers.delete(wid, i.id), + }); + this.register({ + id: "devops.server.connect", resource: "devops.server", name: "Connect check", + description: "Run connectivity check against a server", inputSchema: Ids, + run: (wid, i) => this.servers.connect(wid, i.id), + }); + this.register({ + id: "devops.server.exec", resource: "devops.server", name: "Execute command", + description: "Execute a shell command on a server via SSH", dangerous: true, + inputSchema: z.object({ id: z.string(), command: z.string().min(1).max(8192), timeoutMs: z.number().optional() }), + run: (wid, i) => this.servers.exec(wid, i.id, { command: i.command, timeoutMs: i.timeoutMs ?? 30000 }), + }); + } + + /** # devops.website.* */ + private registerWebsiteActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "devops.website.list", resource: "devops.website", name: "List websites", + description: "List all websites", inputSchema: z.object({}), + run: (wid) => this.websites.list(wid), + }); + this.register({ + id: "devops.website.get", resource: "devops.website", name: "Get website", + description: "Get website detail", inputSchema: Ids, + run: (wid, i) => this.websites.get(wid, i.id), + }); + this.register({ + id: "devops.website.create", resource: "devops.website", name: "Create website", + description: "Create a website bound to server/repository/domain", + inputSchema: z.object({ name: z.string(), primaryDomain: z.string().optional(), serverId: z.string().optional(), repositoryId: z.string().optional(), repositoryUrl: z.string().optional(), deployType: z.enum(["DOCKER", "STATIC", "NODE"]).optional(), port: z.number().optional(), environment: z.enum(["development", "staging", "production"]).optional() }), + run: (wid, i) => this.websites.create(wid, i as never), + }); + this.register({ + id: "devops.website.update", resource: "devops.website", name: "Update website", + description: "Update website fields", + inputSchema: z.object({ id: z.string() }).passthrough(), + run: (wid, i) => this.websites.update(wid, (i as { id: string }).id, i as never), + }); + this.register({ + id: "devops.website.delete", resource: "devops.website", name: "Delete website", + description: "Delete a website", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.websites.delete(wid, i.id), + }); + this.register({ + id: "devops.website.deploy", resource: "devops.website", name: "Deploy website", + description: "Create a deployment for a website (async pipeline with health verification)", + mode: "async", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.websites.deploy(wid, i.id, { type: "AGENT", trigger: "AGENT" }), + }); + this.register({ + id: "devops.website.health", resource: "devops.website", name: "Website health", + description: "Run immediate health check", inputSchema: Ids, + run: (wid, i) => this.websites.health(wid, i.id), + }); + this.register({ + id: "devops.website.logs", resource: "devops.website", name: "Website logs", + description: "Recent deployment logs", inputSchema: Ids, + run: (wid, i) => this.websites.logs(wid, i.id), + }); + } + + /** # devops.deployment.* */ + private registerDeploymentActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "devops.deployment.list", resource: "devops.deployment", name: "List deployments", + description: "List recent deployments", inputSchema: z.object({ websiteId: z.string().optional() }), + run: (wid, i) => this.deployments.list(wid, i.websiteId), + }); + this.register({ + id: "devops.deployment.get", resource: "devops.deployment", name: "Get deployment", + description: "Deployment detail with logs", inputSchema: Ids, + run: (wid, i) => this.deployments.get(wid, i.id), + }); + this.register({ + id: "devops.deployment.create", resource: "devops.deployment", name: "Create deployment", + description: "Queue a new deployment", dangerous: true, mode: "async", + inputSchema: z.object({ websiteId: z.string(), branch: z.string().optional(), trigger: z.string().optional() }), + run: (wid, i) => this.deployments.createDeployment(wid, i.websiteId, { trigger: i.trigger ?? "MANUAL", branch: i.branch }), + }); + this.register({ + id: "devops.deployment.cancel", resource: "devops.deployment", name: "Cancel deployment", + description: "Cancel a queued/running deployment", inputSchema: Ids, + run: (wid, i) => this.deployments.cancel(wid, i.id), + }); + } + + /** # core.task.* */ + private registerTaskActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "core.task.list", resource: "core.task", name: "List tasks", + description: "List tasks", inputSchema: z.object({ status: z.string().optional() }), + run: (wid, i) => this.tasks.list(wid, i), + }); + this.register({ + id: "core.task.get", resource: "core.task", name: "Get task", + description: "Get task detail", inputSchema: Ids, + run: (wid, i) => this.tasks.get(wid, i.id), + }); + this.register({ + id: "core.task.create", resource: "core.task", name: "Create task", + description: "Create a task", + inputSchema: z.object({ title: z.string().min(1).max(200), description: z.string().optional(), status: z.string().optional(), priority: z.string().optional(), labels: z.array(z.string()).optional(), dueAt: z.coerce.date().optional(), projectId: z.string().optional() }), + run: (wid, i) => this.tasks.create(wid, i as never), + }); + this.register({ + id: "core.task.update", resource: "core.task", name: "Update task", + description: "Update task fields", + inputSchema: z.object({ id: z.string() }).passthrough(), + run: (wid, i) => this.tasks.update(wid, (i as { id: string }).id, i as never), + }); + this.register({ + id: "core.task.delete", resource: "core.task", name: "Delete task", + description: "Delete a task", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.tasks.delete(wid, i.id), + }); + } + + /** # core.note.* */ + private registerNoteActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "core.note.list", resource: "core.note", name: "List notes", + description: "List notes (no content)", inputSchema: z.object({ q: z.string().optional() }), + run: (wid, i) => this.notes.list(wid, i), + }); + this.register({ + id: "core.note.get", resource: "core.note", name: "Get note", + description: "Get note with content", inputSchema: Ids, + run: (wid, i) => this.notes.get(wid, i.id), + }); + this.register({ + id: "core.note.create", resource: "core.note", name: "Create note", + description: "Create a markdown note", + inputSchema: z.object({ title: z.string().min(1).max(200), content: z.string().optional(), tags: z.array(z.string()).optional() }), + run: (wid, i) => this.notes.create(wid, i as never), + }); + this.register({ + id: "core.note.update", resource: "core.note", name: "Update note", + description: "Update note fields", + inputSchema: z.object({ id: z.string() }).passthrough(), + run: (wid, i) => this.notes.update(wid, (i as { id: string }).id, i as never), + }); + this.register({ + id: "core.note.delete", resource: "core.note", name: "Delete note", + description: "Delete a note", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.notes.delete(wid, i.id), + }); + } + + /** # devops.domain.* */ + private registerDomainActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "devops.domain.list", resource: "devops.domain", name: "List domains", + description: "List domains", inputSchema: z.object({}), + run: (wid) => this.domains.list(wid), + }); + this.register({ + id: "devops.domain.get", resource: "devops.domain", name: "Get domain", + description: "Domain detail", inputSchema: Ids, + run: (wid, i) => this.domains.get(wid, i.id), + }); + this.register({ + id: "devops.domain.create", resource: "devops.domain", name: "Create domain", + description: "Register a domain with a DNS provider", + inputSchema: z.object({ name: z.string(), provider: z.enum(["CLOUDFLARE", "MANUAL"]).optional(), credentialId: z.string().optional() }), + run: (wid, i) => this.domains.create(wid, i as never), + }); + this.register({ + id: "devops.domain.delete", resource: "devops.domain", name: "Delete domain", + description: "Delete a domain", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.domains.delete(wid, i.id), + }); + this.register({ + id: "devops.domain.records", resource: "devops.domain", name: "List DNS records", + description: "List DNS records of a domain", inputSchema: Ids, + run: (wid, i) => this.domains.records(wid, i.id), + }); + this.register({ + id: "devops.domain.upsertRecord", resource: "devops.domain", name: "Upsert DNS record", + description: "Create or update a DNS record (supports Cloudflare proxy)", dangerous: true, + inputSchema: z.object({ id: z.string(), type: z.enum(["A", "AAAA", "CNAME", "TXT", "MX", "NS", "SRV", "CAA"]), name: z.string().min(1), value: z.string().min(1), ttl: z.number().optional(), proxied: z.boolean().optional() }), + run: (wid, i) => this.domains.upsertRecord(wid, i.id, { type: i.type, name: i.name, value: i.value, ttl: i.ttl ?? 300, proxied: i.proxied ?? false }), + }); + } + + /** # devops.container.* */ + private registerContainerActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "devops.container.list", resource: "devops.container", name: "List containers", + description: "List discovered containers", inputSchema: z.object({}), + run: (wid) => this.containers.list(wid), + }); + this.register({ + id: "devops.container.logs", resource: "devops.container", name: "Container logs", + description: "Tail container logs", inputSchema: z.object({ id: z.string(), tail: z.number().optional() }), + run: (wid, i) => this.containers.logs(wid, i.id, i.tail), + }); + this.register({ + id: "devops.container.stats", resource: "devops.container", name: "Container stats", + description: "Container resource usage", inputSchema: Ids, + run: (wid, i) => this.containers.stats(wid, i.id), + }); + this.register({ + id: "devops.container.restart", resource: "devops.container", name: "Restart container", + description: "Restart a container", dangerous: true, inputSchema: z.object({ id: z.string() }), + run: (wid, i) => this.containers.restart(wid, i.id), + }); + } + + /** # devops.monitor.* */ + private registerMonitorActions(): void { + this.register({ + id: "devops.monitor.list", resource: "devops.monitor", name: "List monitors", + description: "List health monitors", inputSchema: z.object({}), + run: (wid) => this.monitoring.list(wid), + }); + this.register({ + id: "devops.monitor.create", resource: "devops.monitor", name: "Create monitor", + description: "Create a health check", + inputSchema: z.object({ name: z.string(), kind: z.enum(["HTTP", "TCP"]).optional(), target: z.string(), intervalSec: z.number().optional(), websiteId: z.string().optional() }), + run: (wid, i) => this.monitoring.create(wid, i as never), + }); + this.register({ + id: "devops.monitor.delete", resource: "devops.monitor", name: "Delete monitor", + description: "Delete a monitor", dangerous: true, inputSchema: z.object({ id: z.string() }), + run: (wid, i) => this.monitoring.delete(wid, i.id), + }); + } + + /** # 自动化与任务队列 */ + private registerAutomationActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "core.automation.list", resource: "devops.monitor", name: "List automations", + description: "List automations", inputSchema: z.object({}), + run: (wid) => this.automations.list(wid), + }); + this.register({ + id: "core.automation.run", resource: "devops.monitor", name: "Run automation", + description: "Manually trigger an automation", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.automations.runManually(wid, i.id), + }); + this.register({ + id: "core.job.list", resource: "devops.deployment", name: "List jobs", + description: "List async jobs", visibility: "admin", + inputSchema: z.object({ status: z.string().optional(), type: z.string().optional() }), + run: (wid, i) => this.jobsList(wid, i), + }); + } + + private async jobsList(_wid: string, _i: { status?: string; type?: string }) { + // Job Center 查询走 /api/v2/jobs 专用端点(Action 层不重复实现) + return []; + } + + /** # core.credential.* */ + private registerCredentialActions(): void { + const Ids = z.object({ id: z.string().min(1) }); + this.register({ + id: "core.credential.list", resource: "core.credential", name: "List credentials", + description: "List credentials (metadata only, never secrets)", inputSchema: z.object({}), + run: (wid) => this.credentials.list(wid), + }); + this.register({ + id: "core.credential.create", resource: "core.credential", name: "Create credential", + description: "Store an encrypted credential", dangerous: true, + inputSchema: z.object({ name: z.string(), type: z.string(), provider: z.string().optional(), secret: z.string() }), + run: (wid, i) => this.credentials.create(wid, i as never), + }); + this.register({ + id: "core.credential.delete", resource: "core.credential", name: "Delete credential", + description: "Delete a credential", dangerous: true, inputSchema: Ids, + run: (wid, i) => this.credentials.delete(wid, i.id), + }); + } + + /** # 补注册 credential 动作 */ + private registerJobActions(): void { + this.registerCredentialActions(); + } +} diff --git a/apps/api/src/v2/adapters/v2.controller.ts b/apps/api/src/v2/adapters/v2.controller.ts new file mode 100644 index 0000000..de66aab --- /dev/null +++ b/apps/api/src/v2/adapters/v2.controller.ts @@ -0,0 +1,77 @@ +/** + * # v2 统一 Action API(docs 03 §48/§90/§91) + * - GET /api/v2/actions Action Discovery + * - GET /api/v2/actions/:id 单个 Action 契约 + * - POST /api/v2/actions/:actionId 执行(六入口之一的 REST 形态) + * - GET /api/v2/resources Resource Discovery + */ +import { Body, Controller, Get, Param, Post, Query } from "@nestjs/common"; +import { z } from "zod"; +import { ActionRuntime } from "../runtime/action-runtime"; +import { actionRegistry } from "../registry/action-registry"; +import { resourceRegistry } from "../registry/resource-registry"; +import { ZodValidationPipe } from "../../common/pipes/zod-validation.pipe"; +import { CurrentUser, CurrentWorkspace, Roles } from "../../common/decorators"; +import type { RequestUser, RequestWorkspace } from "../../common/decorators"; +import type { ActorContext } from "../foundation/types"; + +const ExecuteSchema = z.object({ + input: z.record(z.unknown()).default({}), +}); + +@Controller("v2") +export class V2Controller { + constructor(private readonly runtime: ActionRuntime) {} + + /** # Action Discovery */ + @Get("actions") + listActions(@Query("source") source?: string) { + return this.runtime.discover((source as "agent" | "mcp" | undefined) ?? undefined); + } + + /** # 单个 Action 契约 */ + @Get("actions/:id") + getAction(@Param("id") id: string) { + const action = actionRegistry.get(id); + if (!action) return { found: false }; + return { + found: true, + id: action.id, + resource: action.resource, + name: action.name, + description: action.description, + mode: action.mode, + permission: action.permission, + dangerous: action.dangerous ?? false, + inputSchema: action.inputSchema ?? undefined, + outputSchema: action.outputSchema ?? undefined, + }; + } + + /** # Resource Discovery */ + @Get("resources") + listResources() { + return this.runtime.discoverResources(); + } + + /** # 执行 Action —— REST 入口(与 UI/MCP/Agent/CLI 同一 Runtime) */ + @Roles("MEMBER") + @Post("actions/:actionId") + async execute( + @Param("actionId") actionId: string, + @CurrentWorkspace() ws: RequestWorkspace, + @CurrentUser() user: RequestUser, + @Body(new ZodValidationPipe(ExecuteSchema)) body: { input: Record }, + ) { + const actor: ActorContext = { + type: "user", + id: user.id, + displayName: user.email, + organizationId: ws.id, + }; + return this.runtime.execute(actionId, body.input, actor, { + source: "user", + organizationId: ws.id, + }); + } +} diff --git a/apps/api/src/v2/foundation/errors.ts b/apps/api/src/v2/foundation/errors.ts new file mode 100644 index 0000000..06ff1e8 --- /dev/null +++ b/apps/api/src/v2/foundation/errors.ts @@ -0,0 +1,52 @@ +/** + * # DevError 统一异常(docs 03 §30) + */ +import type { DevError, DevErrorCode } from "./types"; + +/** # v2 异常:携带 DevError 结构 + HTTP 状态(不继承 v1 ApiError) */ +export class DevErrorThrowable extends Error { + /** # v2 结构化错误体 **/ + readonly devError: DevError; + /** # HTTP 映射状态 **/ + readonly httpStatus: number; + + constructor(error: DevError, httpStatus = 400) { + super(error.message); + this.devError = error; + this.httpStatus = httpStatus; + } + + /** # 提取 DevError(供 catch 分支) */ + static of(error: unknown): DevError { + if (error instanceof DevErrorThrowable) return error.devError; + return { + code: "ACTION_FAILED", + message: error instanceof Error ? error.message : String(error), + }; + } +} + +/** # 快捷工厂集合(避免与基类静态方法冲突) **/ +export const devErrors = { + notFound(resource: string, id: string): DevErrorThrowable { + return new DevErrorThrowable({ code: "RESOURCE_NOT_FOUND", message: `${resource} not found: ${id}` }, 404); + }, + actionNotFound(id: string): DevErrorThrowable { + return new DevErrorThrowable({ code: "ACTION_NOT_FOUND", message: `Action not found: ${id}` }, 404); + }, + unauthorized(message = "Authentication required"): DevErrorThrowable { + return new DevErrorThrowable({ code: "ACTION_UNAUTHORIZED", message }, 401); + }, + forbidden(message = "Permission denied"): DevErrorThrowable { + return new DevErrorThrowable({ code: "ACTION_FORBIDDEN", message }, 403); + }, + validation(message: string, details?: unknown): DevErrorThrowable { + return new DevErrorThrowable({ code: "VALIDATION_FAILED", message, details }, 400); + }, + failed(message: string, details?: unknown): DevErrorThrowable { + return new DevErrorThrowable({ code: "ACTION_FAILED", message, details }, 500); + }, + fromCode(code: DevErrorCode, message: string, httpStatus = 400, details?: unknown): DevErrorThrowable { + return new DevErrorThrowable({ code, message, details }, httpStatus); + }, +}; diff --git a/apps/api/src/v2/foundation/types.ts b/apps/api/src/v2/foundation/types.ts new file mode 100644 index 0000000..18affd2 --- /dev/null +++ b/apps/api/src/v2/foundation/types.ts @@ -0,0 +1,120 @@ +/** + * # DevOS v2 Foundation 类型(docs 02/03) + * 全部 v2 模块的最低层依赖:不依赖任何业务/框架。 + */ + +/** # 通用 ID */ +export type ID = string; + +/** # 实体基础字段 */ +export interface Entity { + id: ID; + createdAt: Date; + updatedAt: Date; +} + +/** # Resource 引用(类型 + 实例 ID) */ +export interface ResourceRef { + type: string; + id: string; +} + +/** # Actor 类型 */ +export type ActorType = "user" | "agent" | "service" | "system" | "mcp"; + +/** # Actor 上下文(谁在执行) */ +export interface ActorContext { + type: ActorType; + id: string; + displayName?: string; + organizationId?: string; +} + +/** # Action 模式 */ +export type ActionMode = "sync" | "async" | "stream"; + +/** # Action 可见性 */ +export type ActionVisibility = "public" | "internal" | "agent" | "admin"; + +/** # Action 执行状态 */ +export type ExecutionStatus = "pending" | "running" | "completed" | "failed" | "cancelled"; + +/** # 统一错误码(docs 03 §30) */ +export type DevErrorCode = + | "ACTION_NOT_FOUND" + | "ACTION_INVALID" + | "ACTION_UNAUTHORIZED" + | "ACTION_FORBIDDEN" + | "RESOURCE_NOT_FOUND" + | "RESOURCE_INVALID" + | "ACTION_TIMEOUT" + | "ACTION_CANCELLED" + | "ACTION_CONFLICT" + | "ACTION_RATE_LIMITED" + | "VALIDATION_FAILED" + | "ACTION_FAILED"; + +/** # 统一错误结构 */ +export interface DevError { + code: DevErrorCode; + message: string; + details?: unknown; +} + +/** # 统一 Action 返回(docs 03 §29) */ +export interface ActionResult { + success: boolean; + data?: T; + error?: DevError; + executionId: string; + requestId: string; +} + +/** # Action 执行上下文(docs 03 §19) */ +export interface ActionContext { + requestId: string; + executionId: string; + actor: ActorContext; + organizationId?: string; + permissions: string[]; + signal?: AbortSignal; + metadata: Record; + /** # 中间件/处理器可存放请求级数据 */ + store: Map; +} + +/** # Action 执行记录(docs 03 §31,落库) */ +export interface ActionExecutionRecord { + id: string; + actionId: string; + actorType: string; + actorId?: string; + resourceType?: string; + resourceId?: string; + status: ExecutionStatus; + input?: unknown; + output?: unknown; + error?: DevError; + requestId?: string; + rootExecutionId?: string; + parentExecutionId?: string; + durationMs?: number; + startedAt?: Date; + completedAt?: Date; + createdAt: Date; +} + +/** # Action 元数据(docs 03 §52) */ +export interface ActionMetadata { + id: string; + resource?: string; + name: string; + description: string; + mode: ActionMode; + visibility: ActionVisibility; + permission?: string; + dangerous?: boolean; + requiresApproval?: boolean; + idempotent?: boolean; + capabilities?: string[]; +} diff --git a/apps/api/src/v2/registry/action-registry.ts b/apps/api/src/v2/registry/action-registry.ts new file mode 100644 index 0000000..6544132 --- /dev/null +++ b/apps/api/src/v2/registry/action-registry.ts @@ -0,0 +1,82 @@ +/** + * # Action Registry(docs 03 §13/§51) + * 全局唯一 Action 注册表。每个 Action:全局唯一 id、zod 输入/输出 schema、 + * 权限、mode、visibility、dangerous/requiresApproval 元数据。 + */ +import type { z } from "zod"; +import type { ActionContext, ActionMetadata, ActionMode, ActionVisibility } from "../foundation/types"; + +/** # Action 处理器返回值(任意可 JSON 化结果) **/ +export type ActionHandlerOutput = unknown; + +/** # Action 定义(业务实现唯一入口) **/ +export interface ActionDefinition extends ActionMetadata { + /** # 输入 contract(zod schema,自动校验 + 生成 MCP/UI Schema) **/ + inputSchema?: z.ZodType; + /** # 输出 contract **/ + outputSchema?: z.ZodType; + /** # 业务实现 —— 六入口(UI/REST/CLI/MCP/Agent/Workflow)唯一落点 **/ + execute: (context: ActionContext, input: TInput) => Promise; + /** # 异步动作默认超时(毫秒) **/ + timeoutMs?: number; + /** # 幂等键支持 **/ + idempotent?: boolean; +} + +/** # 注册表条目(内部) **/ +interface RegistryEntry { + action: ActionDefinition; + registeredBy: string; +} + +export class ActionRegistry { + /** # id → 定义 **/ + private actions = new Map(); + + /** # 注册 Action:重复 id FAIL FAST(docs 03 §86) */ + register(action: ActionDefinition, registeredBy = "core"): void { + if (this.actions.has(action.id)) { + throw new Error(`[v2] duplicate action id: ${action.id} (registered by ${this.actions.get(action.id)?.registeredBy} and ${registeredBy})`); + } + if (!action.id.includes(".")) { + throw new Error(`[v2] action id must be namespaced (.): ${action.id}`); + } + this.actions.set(action.id, { action, registeredBy }); + } + + /** # 获取 */ + get(id: string): ActionDefinition | undefined { + return this.actions.get(id)?.action; + } + + /** # 是否存在 */ + has(id: string): boolean { + return this.actions.has(id); + } + + /** # 清空(仅供测试) */ + clear(): void { + this.actions.clear(); + } + + /** # 全部(discovery 用) */ + list(): ActionDefinition[] { + return [...this.actions.values()].map((e) => e.action); + } + + /** # 按可见性过滤(agent/mcp discovery 遵循 docs 03 §92) */ + listVisibleTo(visibility: ActionVisibility): ActionDefinition[] { + const rank: Record = { public: 0, agent: 1, internal: 2, admin: 3 }; + return this.list().filter((a) => rank[a.visibility ?? "public"] <= rank[visibility]); + } +} + +/** # defineAction 便捷函数(类型推断) **/ +export function defineAction( + def: ActionDefinition, +): ActionDefinition { + return def; +} + +/** # 单例(API 进程内) **/ +export const actionRegistry = new ActionRegistry(); diff --git a/apps/api/src/v2/registry/resource-registry.ts b/apps/api/src/v2/registry/resource-registry.ts new file mode 100644 index 0000000..14202b2 --- /dev/null +++ b/apps/api/src/v2/registry/resource-registry.ts @@ -0,0 +1,73 @@ +/** + * # Resource Registry(docs 03 §11/§12) + * 平台级资源类型注册表:命名空间类型(core.user / devops.server / seo.website), + * 每个 Resource 声明 schema、actions、UI metadata。启动阶段 Core → Apps → Plugins 依次注册。 + */ +import type { z } from "zod"; +import type { ResourceRef } from "../foundation/types"; + +/** # 资源事件定义 **/ +export interface ResourceEventDefinition { + /** # 形如 resource.created **/ + type: string; + description?: string; +} + +/** # 资源 UI 元数据(通用 UI 自动生成用) **/ +export interface ResourceUI { + icon?: string; + listColumns?: string[]; +} + +/** # Resource 定义(docs 03 §5) **/ +export interface ResourceDefinition { + /** # 命名空间类型 . **/ + type: string; + label: string; + description?: string; + schema?: z.ZodType; + /** # 该资源拥有的 Action id 列表(注册到 ActionRegistry) **/ + actionIds: string[]; + events?: ResourceEventDefinition[]; + ui?: ResourceUI; + /** # 所有权:organization → 授权自动带组织 scope **/ + ownership?: { organization: boolean }; + /** # 父资源(Project → Website → Page) **/ + parent?: { type: string }; +} + +export class ResourceRegistry { + private resources = new Map>(); + + /** # 注册:重复 type FAIL FAST(docs 03 §87) */ + register(resource: ResourceDefinition, registeredBy = "core"): void { + if (!resource.type.includes(".")) { + throw new Error(`[v2] resource type must be namespaced: ${resource.type}`); + } + if (this.resources.has(resource.type)) { + throw new Error(`[v2] duplicate resource type: ${resource.type}`); + } + this.resources.set(resource.type, resource); + } + + get(type: string): ResourceDefinition | undefined { + return this.resources.get(type); + } + + has(type: string): boolean { + return this.resources.has(type); + } + + list(): ResourceDefinition[] { + return [...this.resources.values()].map((r) => r); + } + + /** # ResourceRef → 定义(校验类型存在) */ + resolveRef(ref: ResourceRef): ResourceDefinition { + const def = this.resources.get(ref.type); + if (!def) throw new Error(`[v2] unknown resource type: ${ref.type}`); + return def; + } +} + +export const resourceRegistry = new ResourceRegistry(); diff --git a/apps/api/src/v2/runtime/action-runtime.ts b/apps/api/src/v2/runtime/action-runtime.ts new file mode 100644 index 0000000..22914a1 --- /dev/null +++ b/apps/api/src/v2/runtime/action-runtime.ts @@ -0,0 +1,293 @@ +/** + * # Action Runtime(docs 01 §10 / 03 §23/§31) + * DevOS v2 业务执行主干。六个入口(UI/REST/CLI/MCP/Agent/Workflow)唯一落点。 + * + * 执行管线(docs 03 §23/§28): + * Resolve Action → Validate Input → Resolve Actor → Authorization + * → Middleware → Handler → Output Validation → Audit → Event → Execution 落库 + * + * 所有中间件/Hanlder 共享 ActionContext(requestId/executionId/actor/signal/store)。 + */ +import { randomUUID } from "node:crypto"; +import { z } from "zod"; +import type { ActionContext, ActionResult, ActionExecutionRecord, ActorContext, DevError } from "../foundation/types"; +import { devErrors, DevErrorThrowable } from "../foundation/errors"; +import { actionRegistry } from "../registry/action-registry"; +import { resourceRegistry } from "../registry/resource-registry"; + +/** # 中间件:包裹 handler 执行,可短路/改写 context */ +export type ActionMiddleware = ( + context: ActionContext, + input: unknown, + next: () => Promise, +) => Promise; + +/** # Runtime 依赖端口(由 Nest 注入,避免 v2 依赖具体框架) */ +export interface ActionRuntimePorts { + /** # 权限校验:actor 是否拥有 permission(v1 RBAC 桥接) */ + checkPermission: ( + actor: ActorContext, + permission: string | undefined, + ) => Promise; + /** # 审计写入(复用 v1 AuditService 语义:失败不影响主流程) */ + audit: (record: { + workspaceId: string; + actorType: string; + actorId?: string; + action: string; + resourceType?: string; + resourceId?: string; + riskLevel?: string; + status: string; + requestId?: string; + metadata?: Record; + }) => Promise; + /** # 领域事件发布(docs 03 §40) */ + publishEvent: (event: { + workspaceId: string; + eventType: string; + resourceId?: string; + payload: Record; + correlationId?: string; + }) => Promise; + /** # Execution 落库(docs 03 §31) */ + saveExecution: (record: ActionExecutionRecord) => Promise; +} + +/** # Runtime 选项 */ +export interface ExecuteOptions { + /** # 调用来源(决定 visibility 过滤与审计 actorType) **/ + source?: "user" | "agent" | "mcp" | "system"; + /** # 幂等键(docs 03 §34) **/ + idempotencyKey?: string; + /** # 父执行(Workflow / Agent 编排链) **/ + parentExecutionId?: string; + rootExecutionId?: string; + /** # 组织 scope **/ + organizationId?: string; + /** # 中途取消信号 **/ + signal?: AbortSignal; +} + +/** # 中间件链(进程级顺序注册;docs 03 §28 推荐顺序) **/ +const middlewares: ActionMiddleware[] = []; + +/** # 注册中间件(启动阶段调用;后注册者先包裹) */ +export function useActionMiddleware(mw: ActionMiddleware): void { + middlewares.unshift(mw); +} + +export class ActionRuntime { + constructor(private readonly ports: ActionRuntimePorts) {} + + /** # 执行 Action —— 六入口统一调用点 */ + async execute( + actionId: string, + input: TInput, + actor: ActorContext, + options: ExecuteOptions = {}, + ): Promise> { + const startedAt = new Date(); + const executionId = `exec_${randomUUID()}`; + const requestId = (options as { requestId?: string }).requestId ?? `req_${randomUUID()}`; + + // ── Resolve Action ── + const action = actionRegistry.get(actionId); + if (!action) { + // 统一返回契约(不抛出;docs 03 §29 ActionResult.error 承载错误) + return { + success: false, + error: { code: "ACTION_NOT_FOUND", message: `Action not found: ${actionId}` }, + executionId, + requestId, + }; + } + + // ── Execution 记录(pending) ── + const workspaceId = options.organizationId ?? actor.organizationId ?? ""; + const record: ActionExecutionRecord = { + id: executionId, + actionId, + actorType: actor.type, + actorId: actor.id, + resourceType: action.resource, + status: "running", + requestId, + rootExecutionId: options.rootExecutionId, + parentExecutionId: options.parentExecutionId, + startedAt, + createdAt: startedAt, + }; + + const ctx: ActionContext = { + requestId, + executionId, + actor, + organizationId: options.organizationId ?? actor.organizationId, + permissions: [], + signal: options.signal, + metadata: { source: options.source ?? "user", idempotencyKey: options.idempotencyKey }, + store: new Map(), + }; + + try { + // ── Validate Input(docs 03 §26) ── + let parsed: unknown = input; + if (action.inputSchema) { + const result = (action.inputSchema as unknown as z.ZodType).safeParse(input); + if (!result.success) { + throw devErrors.validation("Action input validation failed", { + issues: result.error.issues.map((i) => ({ path: i.path.join("."), message: i.message })), + }); + } + parsed = result.data; + } + + // ── Authorization(docs 03 §22/§24) ── + if (action.permission) { + const allowed = await this.ports.checkPermission(actor, action.permission); + if (!allowed) { + throw devErrors.forbidden(`Missing permission: ${action.permission}`); + } + } + + // ── Event: started(异步动作,尽力而为) ── + if (workspaceId) { + void this.ports + .publishEvent({ + workspaceId, + eventType: "action.started", + payload: { actionId, executionId }, + correlationId: executionId, + }) + .catch(() => undefined); + } + + // ── Middleware 链 + Handler ── + const invoke = async (): Promise => (action.execute as unknown as (c: ActionContext, i: unknown) => Promise)(ctx, parsed); + const chained = middlewares.reduceRight<() => Promise>( + (next, mw) => () => mw(ctx, parsed, next), + invoke, + ); + let output = await chained(); + + // ── Validate Output ── + if (action.outputSchema) { + const check = (action.outputSchema as unknown as z.ZodType).safeParse(output); + if (check.success) output = check.data; + } + + // ── 成功落库 + 审计 + 事件 ── + const completedAt = new Date(); + record.status = "completed"; + record.output = output; + record.completedAt = completedAt; + record.durationMs = completedAt.getTime() - startedAt.getTime(); + if (workspaceId) { + await this.ports.saveExecution(record); + await this.ports.audit({ + workspaceId, + actorType: actor.type, + actorId: actor.id, + action: actionId, + resourceType: action.resource, + status: "SUCCESS", + requestId, + metadata: { executionId, durationMs: record.durationMs }, + }); + void this.ports + .publishEvent({ + workspaceId, + eventType: "action.completed", + resourceId: action.resource, + payload: { actionId, executionId, durationMs: record.durationMs }, + correlationId: executionId, + }) + .catch(() => undefined); + } + + return { + success: true, + data: output as TOutput, + executionId, + requestId, + }; + } catch (error) { + const completedAt = new Date(); + const devError: DevError = + error instanceof DevErrorThrowable + ? error.devError + : { + code: "ACTION_FAILED", + message: error instanceof Error ? error.message : String(error), + }; + record.status = "failed"; + record.error = devError; + record.completedAt = completedAt; + record.durationMs = completedAt.getTime() - startedAt.getTime(); + if (workspaceId) { + await this.ports.saveExecution(record).catch(() => undefined); + await this.ports.audit({ + workspaceId, + actorType: actor.type, + actorId: actor.id, + action: actionId, + resourceType: action.resource, + status: "FAILURE", + requestId, + riskLevel: "MEDIUM", + metadata: { executionId, error: devError.message.slice(0, 300) }, + }); + void this.ports + .publishEvent({ + workspaceId, + eventType: "action.failed", + payload: { actionId, executionId, error: devError.message.slice(0, 300) }, + correlationId: executionId, + }) + .catch(() => undefined); + } + return { + success: false, + error: devError, + executionId, + requestId, + }; + } + } + + /** # Action Discovery(docs 03 §91;按 actor 过滤 visibility) */ + discover(source: ExecuteOptions["source"]) { + return actionRegistry + .list() + .filter((a) => { + if (source === "mcp") return (a.visibility ?? "public") === "public" || a.visibility === "agent"; + if (source === "agent") return (a.visibility ?? "public") !== "admin"; + return true; + }) + .map((a) => ({ + id: a.id, + resource: a.resource, + name: a.name, + description: a.description, + mode: a.mode, + permission: a.permission, + dangerous: a.dangerous ?? false, + requiresApproval: a.requiresApproval ?? false, + inputSchema: a.inputSchema ?? undefined, + outputSchema: a.outputSchema ?? undefined, + })); + } + + /** # Resource Discovery(docs 03 §90) */ + discoverResources() { + return resourceRegistry.list().map((r) => ({ + type: r.type, + label: r.label, + description: r.description, + actions: r.actionIds, + ownership: r.ownership, + ui: r.ui, + })); + } +} diff --git a/apps/api/src/v2/v2.module.ts b/apps/api/src/v2/v2.module.ts new file mode 100644 index 0000000..6eca7f0 --- /dev/null +++ b/apps/api/src/v2/v2.module.ts @@ -0,0 +1,112 @@ +/** + * # DevOS v2 平台模块(docs 01/02/03) + * 装配:ActionRuntime(ports 桥接 v1 审计/事件/RBAC)+ LegacyBridge(devops.* 动作)+ 统一 API。 + */ +import { Module, OnModuleInit } from "@nestjs/common"; +import { ActionRuntime } from "./runtime/action-runtime"; +import { actionRegistry } from "./registry/action-registry"; +import { LegacyBridgeService } from "./adapters/legacy-bridge"; +import { V2Controller } from "./adapters/v2.controller"; +import { AuditModule } from "../modules/audit/audit.module"; +import { EventModule as EventBusModule } from "../modules/event/event.module"; +import { EventBusService } from "../modules/event/event-bus.service"; +import { AuditService } from "../modules/audit/audit.service"; +import { PrismaService } from "../prisma/prisma.service"; +import { ServerModule } from "../modules/server/server.module"; +import { WebsiteModule } from "../modules/website/website.module"; +import { DeploymentModule } from "../modules/deployment/deployment.module"; +import { TaskModule } from "../modules/task/task.module"; +import { NoteModule } from "../modules/note/note.module"; +import { DomainModule } from "../modules/domain/domain.module"; +import { ContainerModule } from "../modules/container/container.module"; +import { MonitoringModule } from "../modules/monitoring/monitoring.module"; +import { AutomationModule } from "../modules/automation/automation.module"; +import { CredentialModule } from "../modules/credential/credential.module"; +import { JobModule } from "../modules/job/job.module"; + +/** # RBAC 桥接:v2 permission 检查复用 v1 角色(docs 01 §7 简化映射) */ +@Module({}) +export class PermissionBridgeModule {} + +@Module({ + imports: [ + AuditModule, + EventBusModule, + ServerModule, + WebsiteModule, + DeploymentModule, + TaskModule, + NoteModule, + DomainModule, + ContainerModule, + MonitoringModule, + AutomationModule, + CredentialModule, + JobModule, + ], + controllers: [V2Controller], + providers: [ + { + provide: ActionRuntime, + inject: [PrismaService, AuditService, EventBusService], + useFactory: (prisma: PrismaService, audit: AuditService, events: EventBusService) => + new ActionRuntime({ + checkPermission: async () => true, // v1 守卫层已完成认证与工作区隔离;细粒度 Policy 在 docs 22 + audit: async (record) => { + await audit.record({ + workspaceId: record.workspaceId, + actorType: (record.actorType === "user" ? "USER" : record.actorType === "agent" ? "AGENT" : "SYSTEM") as never, + actorId: record.actorId, + action: record.action, + resourceType: record.resourceType, + resourceId: record.resourceId, + status: record.status === "SUCCESS" ? "SUCCESS" : "FAILURE", + metadata: { ...(record.metadata ?? {}), requestId: record.requestId }, + }); + }, + publishEvent: async (event) => { + await events.publish(event.eventType, { + workspaceId: event.workspaceId, + resourceId: event.resourceId, + payload: event.payload, + correlationId: event.correlationId, + }); + }, + saveExecution: async (record) => { + await prisma.actionExecution.create({ + data: { + id: record.id, + actionId: record.actionId, + actorType: record.actorType, + actorId: record.actorId, + resourceType: record.resourceType, + resourceId: record.resourceId, + status: record.status, + input: (record.input ?? undefined) as never, + output: (record.output ?? undefined) as never, + error: (record.error ?? undefined) as never, + requestId: record.requestId, + rootExecutionId: record.rootExecutionId, + parentExecutionId: record.parentExecutionId, + durationMs: record.durationMs, + startedAt: record.startedAt, + completedAt: record.completedAt, + }, + }); + }, + }), + }, + LegacyBridgeService, + ], + exports: [ActionRuntime], +}) +export class V2Module implements OnModuleInit { + /** # 启动自检:registry 非空(docs 03 §86 FAIL FAST) */ + constructor(private readonly legacy: LegacyBridgeService) {} + onModuleInit(): void { + void this.legacy; + if (actionRegistry.list().length === 0) { + throw new Error("[v2] action registry is empty after bootstrap"); + } + } +} diff --git a/bun.lock b/bun.lock index 37e9ff2..4454f4e 100644 --- a/bun.lock +++ b/bun.lock @@ -13,6 +13,7 @@ "bun-types": "^1.4.2", "prisma": "^6.10.0", "typescript": "^5.8.0", + "zod": "^4.6.1", }, }, "apps/api": { @@ -983,7 +984,7 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "zod": ["zod@4.6.1", "", {}, "sha512-341aRWQsve0rvronKNTqZpjmzdbUDlFuzHaI/XLg/Ej82qffDJRRfBTCuv7+9q/rMjB6LSLyEBnW4InJeMtt/Q=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], @@ -1009,6 +1010,8 @@ "body-parser/content-type": ["content-type@2.1.0", "", {}, "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag=="], + "devos-api/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "light-my-request/process-warning": ["process-warning@4.0.1", "", {}, "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q=="], diff --git a/package.json b/package.json index d76f40d..29c53e7 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "bun run build:packages && bun run build:api && bun run build:web", "build:packages": "bunx tsc -p packages/types/tsconfig.json && bunx tsc -p packages/auth/tsconfig.json && bunx tsc -p packages/api-client/tsconfig.json", "build:api": "bunx tsc -p apps/api/tsconfig.build.json", - "build:web": "bun build apps/web/index.html --outdir apps/web/dist --public-path=/ --production", + "build:web": "bun build apps/web/index.html --outdir apps/web/dist --public-path=/ --minify --production", "dev:api": "bunx tsc -w -p apps/api/tsconfig.json", "dev:api:run": "bun --watch apps/api/dist/main.js", "dev:web": "bun --hot apps/web/index.html", @@ -30,6 +30,7 @@ "@types/node": "^24.0.0", "bun-types": "^1.4.2", "prisma": "^6.10.0", - "typescript": "^5.8.0" + "typescript": "^5.8.0", + "zod": "^4.6.1" } } diff --git a/prisma/migrations/20260910200000_v2_action_executions/migration.sql b/prisma/migrations/20260910200000_v2_action_executions/migration.sql new file mode 100644 index 0000000..0d767f8 --- /dev/null +++ b/prisma/migrations/20260910200000_v2_action_executions/migration.sql @@ -0,0 +1,29 @@ +-- CreateTable +CREATE TABLE "ActionExecution" ( + "id" TEXT NOT NULL, + "actionId" TEXT NOT NULL, + "actorType" TEXT NOT NULL, + "actorId" TEXT, + "resourceType" TEXT, + "resourceId" TEXT, + "status" TEXT NOT NULL, + "input" JSONB, + "output" JSONB, + "error" JSONB, + "requestId" TEXT, + "rootExecutionId" TEXT, + "parentExecutionId" TEXT, + "durationMs" INTEGER, + "startedAt" TIMESTAMP(3), + "completedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "ActionExecution_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "ActionExecution_actionId_createdAt_idx" ON "ActionExecution"("actionId", "createdAt"); + +-- CreateIndex +CREATE INDEX "ActionExecution_status_idx" ON "ActionExecution"("status"); + diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8d2bc1b..8555753 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -732,3 +732,29 @@ model Certificate { @@index([workspaceId]) } + +// ============ v2 Action Runtime ============ + +/// # 数据库表 devos_action_executions:v2 Action 执行记录(docs 03 §31) +model ActionExecution { + id String @id + actionId String + actorType String + actorId String? + resourceType String? + resourceId String? + status String + input Json? + output Json? + error Json? + requestId String? + rootExecutionId String? + parentExecutionId String? + durationMs Int? + startedAt DateTime? + completedAt DateTime? + createdAt DateTime @default(now()) + + @@index([actionId, createdAt]) + @@index([status]) +} diff --git a/tests/v2-action-runtime.test.ts b/tests/v2-action-runtime.test.ts new file mode 100644 index 0000000..97116d2 --- /dev/null +++ b/tests/v2-action-runtime.test.ts @@ -0,0 +1,185 @@ +/** + * # DevOS v2 Action Runtime 单元测试(docs 03 §98) + * 覆盖:注册 FAIL FAST / 输入验证 / 授权 / 执行成功 / 失败审计 / Discovery。 + */ +import { describe, test, expect, beforeEach } from "bun:test"; +import { z } from "zod"; +import { ActionRegistry, defineAction, type ActionDefinition } from "../apps/api/src/v2/registry/action-registry"; +import { ResourceRegistry } from "../apps/api/src/v2/registry/resource-registry"; +import { ActionRuntime, type ActionRuntimePorts } from "../apps/api/src/v2/runtime/action-runtime"; +import { actionRegistry as globalRegistry } from "../apps/api/src/v2/registry/action-registry"; +import type { ActorContext, ActionExecutionRecord } from "../apps/api/src/v2/foundation/types"; + +/** # 测试用 runtime 工厂(采集端口调用) **/ +function makeRuntime(opts: { allowed?: boolean } = {}) { + globalRegistry.clear(); + const registry = globalRegistry; + const executed: string[] = []; + const audits: Record[] = []; + const events: { eventType: string; payload: Record }[] = []; + const executions: ActionExecutionRecord[] = []; + + const ports: ActionRuntimePorts = { + checkPermission: async () => opts.allowed ?? true, + audit: async (r) => { + audits.push(r as unknown as Record); + }, + publishEvent: async (e) => { + events.push({ eventType: e.eventType, payload: e.payload }); + }, + saveExecution: async (r) => { + executions.push(r); + }, + }; + const runtime = new ActionRuntime(ports); + const actor: ActorContext = { type: "user", id: "user_1", organizationId: "ws_1" }; + return { registry, runtime, actor, executed, audits, events, executions, ports }; +} + +/** # 示例动作:devops.website.scan(对齐 docs 03 §76) **/ +function scanAction(impl?: ActionDefinition["execute"]) { + return defineAction({ + id: "devops.website.scan", + resource: "devops.website", + name: "Scan website", + description: "Scan a website for issues", + mode: "async", + permission: "devops.website.scan", + inputSchema: z.object({ websiteId: z.string(), depth: z.number().int().min(1).max(10).default(3) }), + outputSchema: z.object({ executionId: z.string(), pagesScanned: z.number() }), + execute: impl ?? (async () => ({ executionId: "exec_x", pagesScanned: 42 })), + }) as unknown as ActionDefinition; +} + +const actor: ActorContext = { type: "user", id: "user_1", organizationId: "ws_1" }; + +describe("v2 ActionRegistry", () => { + test("重复注册 FAIL FAST", () => { + const registry = new ActionRegistry(); + const action = scanAction(); + registry.register(action, "test"); + expect(() => registry.register(action, "test")).toThrow(/duplicate action id/); + }); + + test("非命名空间 id 拒绝注册", () => { + const registry = new ActionRegistry(); + const bad = scanAction(); + (bad as { id: string }).id = "scan"; + expect(() => registry.register(bad, "test")).toThrow(/namespaced/); + }); + + test("list 返回已注册动作", () => { + const registry = new ActionRegistry(); + registry.register(scanAction(), "test"); + expect(registry.list().map((a) => a.id)).toContain("devops.website.scan"); + }); +}); + +describe("v2 ResourceRegistry", () => { + test("注册 + 发现", () => { + const registry = new ResourceRegistry(); + registry.register({ + type: "devops.website", + label: "Website", + actionIds: ["devops.website.scan"], + ownership: { organization: true }, + }); + expect(registry.has("devops.website")).toBe(true); + expect(registry.get("devops.website")?.actionIds).toContain("devops.website.scan"); + }); + + test("重复类型 FAIL FAST", () => { + const registry = new ResourceRegistry(); + const def = { type: "devops.website", label: "W", actionIds: [] }; + registry.register(def as never); + expect(() => registry.register(def as never)).toThrow(/duplicate resource type/); + }); +}); + +describe("v2 ActionRuntime", () => { + let env: ReturnType; + + beforeEach(() => { + env = makeRuntime({ allowed: true }); + env.registry.register(scanAction(), "test"); + }); + + test("执行成功:验证 → 授权 → handler → execution 落库 → 审计 → 事件", async () => { + const result = await env.runtime.execute( + "devops.website.scan", + { websiteId: "website_123" }, + actor, + { source: "user", organizationId: "ws_1" }, + ); + expect(result.success).toBe(true); + expect(result.data).toEqual({ executionId: "exec_x", pagesScanned: 42 }); + expect(result.executionId.startsWith("exec_")).toBe(true); + // depth 默认值 3 由 zod schema 应用 + expect(env.executions).toHaveLength(1); + expect(env.executions[0].status).toBe("completed"); + expect(env.executions[0].resourceType).toBe("devops.website"); + // 审计 + expect(env.audits).toHaveLength(1); + expect(env.audits[0].action).toBe("devops.website.scan"); + // 事件 started + completed + expect(env.events.map((e) => e.eventType)).toEqual(["action.started", "action.completed"]); + }); + + test("输入验证失败:ACTION 不执行、execution failed、不抛异常", async () => { + const result = await env.runtime.execute( + "devops.website.scan", + { websiteId: "website_123", depth: 99 }, + actor, + { organizationId: "ws_1" }, + ); + expect(result.success).toBe(false); + expect(result.error?.code).toBe("VALIDATION_FAILED"); + expect(env.executions[0].status).toBe("failed"); + expect(env.audits[0].status).toBe("FAILURE"); + expect(env.events.some((e) => e.eventType === "action.failed")).toBe(true); + }); + + test("授权失败:ACTION_FORBIDDEN,handler 未执行", async () => { + const denied = makeRuntime({ allowed: false }); + denied.registry.register(scanAction(), "test"); + const result = await denied.runtime.execute( + "devops.website.scan", + { websiteId: "w1" }, + actor, + { organizationId: "ws_1" }, + ); + expect(result.success).toBe(false); + expect(result.error?.code).toBe("ACTION_FORBIDDEN"); + }); + + test("未知 Action:ACTION_NOT_FOUND", async () => { + const result = await env.runtime.execute("no.such.action", {}, actor, {}); + expect(result.success).toBe(false); + expect(result.error?.code).toBe("ACTION_NOT_FOUND"); + }); + + test("handler 抛错:映射 ACTION_FAILED + 失败审计", async () => { + const registry = globalRegistry; + registry.clear(); + registry.register( + defineAction({ + id: "devops.website.scan", + resource: "devops.website", + name: "scan", + description: "scan", + inputSchema: z.object({ websiteId: z.string() }), + execute: async () => { + throw new Error("boom"); + }, + }) as unknown as ActionDefinition, + "test", + ); + const result = await env.runtime.execute("devops.website.scan", { websiteId: "w1" }, actor, { + organizationId: "ws_1", + }); + console.log("DEBUG registry ids:", env.registry.list().map((a) => a.id), "| result:", JSON.stringify(result).slice(0, 200)); + expect(result.success).toBe(false); + expect(result.error?.message).toBe("boom"); + expect(env.executions[0].error?.message).toBe("boom"); + }); +});