feat: RFC-003 Adapter Plugin Architecture + Dynamic Prompts #243

Merged
xiaomo merged 2 commits from feat/rfc-003-adapter-packages into main 2026-04-29 07:33:46 +00:00
Owner

What

Adapter plugin architecture for RFC-003 — each agent adapter in its own package, AgentRegistry accepts factories.

Changes

AgentRegistry plugin model

  • createAgentRegistry(agents, adapterFactories) — adapter map as second param
  • Echo built-in, cursor/hermes via factory injection
  • Unknown type throws with available adapter list

Dynamic prompts

  • RoleSpec.prompt: string | ((start, messages) => Promise<string>)
  • compileWorkflowSpec handles both static and dynamic

New packages

  • @uncaged/nerve-adapter-cursor — cursor-agent CLI spawn
  • @uncaged/nerve-adapter-hermes — hermes CLI subagent spawn

Integration

  • Kernel wires default adapter factories, hot-reload passes them

Testing

559 tests, all pass

Ref: #234

## What Adapter plugin architecture for RFC-003 — each agent adapter in its own package, AgentRegistry accepts factories. ## Changes ### AgentRegistry plugin model - `createAgentRegistry(agents, adapterFactories)` — adapter map as second param - Echo built-in, cursor/hermes via factory injection - Unknown type throws with available adapter list ### Dynamic prompts - `RoleSpec.prompt: string | ((start, messages) => Promise<string>)` - `compileWorkflowSpec` handles both static and dynamic ### New packages - `@uncaged/nerve-adapter-cursor` — cursor-agent CLI spawn - `@uncaged/nerve-adapter-hermes` — hermes CLI subagent spawn ### Integration - Kernel wires default adapter factories, hot-reload passes them ## Testing 559 tests, all pass ✅ Ref: #234
xiaoju added 2 commits 2026-04-29 07:27:07 +00:00
- Adapter packages: each adapter in own package (@nerve/adapter-cursor, etc.)
- AgentRegistry accepts adapter factories at construction (plugin model)
- Migration path: move spawn logic from workflow-utils to adapter packages
- Dynamic prompts: RoleSpec.prompt supports string | async function
- Workspace only installs adapters it uses

Ref: #234
AgentRegistry plugin model:
- createAgentRegistry(agents, adapterFactories) — second param for adapter map
- Echo adapter built-in, cursor/hermes via factory injection
- Unknown type throws with available adapter list

Dynamic prompts:
- RoleSpec.prompt: string | ((start, messages) => Promise<string>)
- compileWorkflowSpec handles both static and dynamic prompts

Adapter packages:
- @uncaged/nerve-adapter-cursor — cursor-agent CLI spawn
- @uncaged/nerve-adapter-hermes — hermes CLI subagent spawn
- Each with own spawn-safe (inline, avoids circular dep)
- Moved spawn logic from workflow-utils, kept role factories as thin wrappers

Kernel integration:
- defaultAgentAdapterFactories() registers cursor + hermes
- Hot-reload passes factories on rebuild

Ref: #234
xiaomo approved these changes 2026-04-29 07:33:45 +00:00
xiaomo left a comment
Owner

Hermes Agent Review — APPROVED

总评

Adapter 插件化 + 动态 prompt,架构演进方向正确。插件模式让 adapter 独立包管理,减少不必要依赖;dynamic prompt 解决了实际场景的刚需。

亮点

  • AgentRegistry 插件化createAgentRegistry(agents, adapterFactories) 第二参数注入工厂,echo 内置、cursor/hermes 通过 factory map 注册,扩展性好
  • Dynamic promptsPromptInput = string | ((start, messages) => Promise<string>)compileWorkflowSpec 里 3 行处理,简洁
  • Adapter packages — cursor/hermes 各自独立包,createCursorAdapter / createHermesAdapter 工厂签名统一
  • AbortSignal 全链路 — spawn-safe → adapter → AgentFn,abort 信号贯穿,cancel 机制完整
  • Backward compatworkflow-utils 保留旧的 createCursorRole / createHermesRole,re-export adapter 函数,不 break 现有 workflow

⚠️ 需要关注

  1. spawn-safe.ts 重复adapter-cursor/src/spawn-safe.tsadapter-hermes/src/spawn-safe.ts 是完全相同的 186 行文件(跟 workflow-utils/src/shared/spawn-safe.ts 也高度重叠)。这是 copy-paste,后续改一个忘改另一个会出 bug。建议:

    • 短期:接受现状,三份都有
    • 中期:抽到 @uncaged/nerve-spawn 或放 @uncaged/nerve-core 里共享

    不阻塞合入,但建议开个 issue 跟踪。

  2. defaultAgentAdapterFactories() 每次调用都 import — kernel 里 createCursorAdaptercreateHermesAdapter 是顶层 import,如果 adapter 包未安装会直接 crash。这符合 "no runtime fallback" 策略,但意味着 daemon 包必须 depend on 两个 adapter 包。确认这是有意为之(看 package.json diff 确认 daemon 加了依赖)

💡 Minor

  • hermes-agent.ts 只剩 re-export + options resolution,可以考虑把 options resolution 也移到 adapter-hermes 包,让 workflow-utils 更薄
  • KNOWN_AGENT_ADAPTER_IDS 现在有 cursor/hermes/codex,但 codex adapter 包还没建。不影响运行(validate 只检查 factory map),但 ID 列表和实际 adapter 不一致

Reviewed by 小墨 🖊️

## ✅ Hermes Agent Review — APPROVED ### 总评 Adapter 插件化 + 动态 prompt,架构演进方向正确。插件模式让 adapter 独立包管理,减少不必要依赖;dynamic prompt 解决了实际场景的刚需。 ### ✅ 亮点 - **AgentRegistry 插件化** — `createAgentRegistry(agents, adapterFactories)` 第二参数注入工厂,echo 内置、cursor/hermes 通过 factory map 注册,扩展性好 - **Dynamic prompts** — `PromptInput = string | ((start, messages) => Promise<string>)`,`compileWorkflowSpec` 里 3 行处理,简洁 - **Adapter packages** — cursor/hermes 各自独立包,`createCursorAdapter` / `createHermesAdapter` 工厂签名统一 - **AbortSignal 全链路** — spawn-safe → adapter → AgentFn,abort 信号贯穿,cancel 机制完整 - **Backward compat** — `workflow-utils` 保留旧的 `createCursorRole` / `createHermesRole`,re-export adapter 函数,不 break 现有 workflow ### ⚠️ 需要关注 1. **`spawn-safe.ts` 重复** — `adapter-cursor/src/spawn-safe.ts` 和 `adapter-hermes/src/spawn-safe.ts` 是完全相同的 186 行文件(跟 `workflow-utils/src/shared/spawn-safe.ts` 也高度重叠)。这是 copy-paste,后续改一个忘改另一个会出 bug。建议: - 短期:接受现状,三份都有 - 中期:抽到 `@uncaged/nerve-spawn` 或放 `@uncaged/nerve-core` 里共享 **不阻塞合入**,但建议开个 issue 跟踪。 2. **`defaultAgentAdapterFactories()` 每次调用都 import** — kernel 里 `createCursorAdapter` 和 `createHermesAdapter` 是顶层 import,如果 adapter 包未安装会直接 crash。这符合 "no runtime fallback" 策略,但意味着 daemon 包必须 depend on 两个 adapter 包。确认这是有意为之(看 package.json diff 确认 daemon 加了依赖)✅ ### 💡 Minor - `hermes-agent.ts` 只剩 re-export + options resolution,可以考虑把 options resolution 也移到 adapter-hermes 包,让 workflow-utils 更薄 - `KNOWN_AGENT_ADAPTER_IDS` 现在有 cursor/hermes/codex,但 codex adapter 包还没建。不影响运行(validate 只检查 factory map),但 ID 列表和实际 adapter 不一致 --- *Reviewed by 小墨 🖊️*
xiaomo merged commit 84334b7b09 into main 2026-04-29 07:33:46 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No Label
2 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/nerve#243