跳转到内容

插件开发实践

这些建议供插件作者和编程 Agent 参考,帮助插件与 Wuu 及其他扩展协同工作。请根据插件的实际用途取舍。本文不增加准入检查或新的强制规则;现有 API 和协议要求仍然适用,具体契约以编写参考、桌面插件指南和兼容性参考为准。

  • 根据改动目的选择合适的公开扩展点。增量贡献、局部委托和完整 provider 替换都是同等支持的选择;完整替换不以先尝试增量方案为前提。
  • 使用 @wuu/plugin-sdk 和公开的宿主服务,避免依赖其他插件的私有文件、进程或 renderer 状态。增量插件可以消费现有服务,不必替换其 provider。
  • 运行时在 required_services 中声明使用的服务,桌面插件在 desktop.required_services 中声明。包依赖决定使用哪些包及其激活顺序;服务要求指定 API 名称和主版本。两者都需要时分别声明。
  • 为可选依赖不可用的情况设计明确处理方式,保留无关功能,并报告受到影响的功能。
  • 在兼容更新中保持包、服务和 capability 标识稳定。产品版本、包版本、协议版本和服务主版本分别决定兼容性。
  • 在 initialize 中声明能力,在 prepare 中读取和校验状态,在 activate 中启动定时器、订阅等工作。准备阶段的方法限制见生命周期参考。
  • 在 shutdown 中停止插件拥有的工作,包括准备或激活只完成一部分的情况。视图卸载或桌面代际结束时,清理相应监听器、订阅和定时器。
  • 工具、capability 或服务调用启动的工作使用 execution.signal;运行时后台工作使用 lifecycle.signal;桌面代际工作使用 api.signal。取消需要工作本身配合,也不能撤销已经完成的操作。
  • 前台操作使用对应处理函数收到的 host。避免把某次调用的 host、execution ID 或 signal 保存在共享状态中供其他调用使用。
  • 按重载和停用场景设计激活与清理。普通更新时,旧代际可能继续处理在途工作;提交后的激活失败也不会回滚已产生的外部效果。
  • 工具操作失败时,返回 is_error: true 的工具结果,并说明失败原因。必要操作失败后不要报告成功。保留取消状态,不要把取消报告为成功或自动重试。模型可能看到工具结果的内容。
  • 服务调用方需要区分可预期的失败时,使用有文档说明的稳定错误码,并将错误码与展示文案分开。保留有用的宿主错误码,例如 RuntimeHostServiceError 携带的 code;不要通过解析错误文本决定处理逻辑。
  • 按 capability 的用途选择 error_policy。观察行为失败不应中断被观察的工作:需要诊断时使用 isolate,只有可以接受无诊断地继续时才考虑 ignore。对于决策或转换,考虑缺少该贡献时继续执行是否安全。必要的授权或安全检查失败时,报告失败,不要静默放行。各 capability 的限制以编写参考为准。
  • 在受影响的工具、服务或界面中报告操作失败。已知时说明操作、影响和可采取的下一步。默认不要在错误和诊断中放入令牌、凭据、对话内容或私人文件内容。
  • 写入超时或失败,但操作可能已经生效时,将结果报告为未知。如果操作支持安全查询,重试前先读取当前状态;没有证据时不要声称已经回滚。
  • JSONL 运行时将 stdout 留给协议消息,诊断写入 stderr。处理后台 Promise 的拒绝,使失败能归因到对应插件。
  • 在使用处校验工具参数和外部数据,包括声明的 schema 无法表达的约束。在 activity 中如实声明工具的副作用和并发属性;只有共享状态安全时才启用并发执行。
  • 从当前回调的执行上下文获取会话和工作区身份。缺少身份时,不要借用当前选中的会话,也不要把界面快照当成执行操作的权限。
  • 将持久化业务状态保存在合适的宿主存储或服务中。对同一个 host.storage 值进行竞争性的读改写时,使用 host.storage.compare_exchange,检查结果并限制重试次数。其他状态服务和 provider 使用各自的并发或事务契约。停用或重载插件时保留用户数据。
  • 为非密钥设置选择合适的 live、next-operation 或 restart 生效方式。一次操作需要多项关联设置保持一致时,先获取配置快照。相关设置放在同一 scope;合并的用户与工作区快照不提供跨 scope 事务。
  • 对受支持的认证请求使用宿主凭据服务。不要将密钥放入工具参数、普通设置或存储、日志或打包文件。插件代码受信任并使用用户权限运行;权限声明不会为插件创建沙箱。
  • 使用宿主的 React 实例、UI Kit、主题 token 和本地化文本。添加小控件或注释时,优先使用已有的增量 slot,而不是替换整个输入框、会话或 shell。
  • 将快照视为只读数据。wrapper 不处理某个项目时应保留 children;presenter 可以用 next() 交给后续处理。避免依赖私有 DOM 选择器和内部 React 状态。
  • 在受影响的视图中处理异步操作失败。可选界面贡献失败时,避免把无关工作展示为失败;视图卸载时释放其拥有的资源。

按任务选择验证方式:本地试用和开发运行相关检查并实际执行改动的行为;合并和发布遵循各自适用的检查要求。这些建议不会将本地试用升级为发布流程。

  • 对打包插件,可用 wuu plugin validate 检查包结构,用 wuu plugin test 检查初始化与协议协商。这些检查不能证明工具结果或桌面界面正常。
  • 根据改动,在真实会话或桌面视图中执行相关功能。界面改动应检查实际渲染,不能仅凭注册成功判断。
  • 根据功能检查操作失败、取消、停用和重载。涉及持久化或外部写入时,检查失败后的状态;结果未知时不要重复执行可能产生副作用的操作。
  • 本地运行时也可以使用agent 快速开始中的单文件开发路径。报告已验证的行为和无法实际验证的部分。