Account provider and active request cancellation
账号提供方与当前请求取消
Selecting credentials from login state changes the billing identity of an existing provider route. Sign-out also needs to stop account-dependent work without classifying requests from settings that may have changed while a request or tool is still running.
English
Problem
Selecting credentials from login state changes the billing identity of an existing provider route. Sign-out also needs to stop account-dependent work without classifying requests from settings that may have changed while a request or tool is still running.
Decision
deepseek-official and deepseek-account are independent routes sharing the DeepSeek protocol implementation. Each adapter has exactly one credential resolver and authentication header mode. Neither route falls back to the other credential. The account service retains the origin and issuer validation defined by the login decision.
Account cancellation reads each running Agent’s latest Session.requestContext() instead of maintaining another provider field. This logged value remains through tools and retries and follows the next bound request. Idle Agents are excluded. During a new turn’s first preparation it can still name the previous turn’s account route, so sign-out can also interrupt an API-key turn that has not bound its new request yet. A missing account credential rejects a first request without a previous context before transport.
Successful local sign-out publishes an account event. The platform account provider installs the account module’s listener, which enumerates the Agent registry and cancels matching account routes through Agent.cancel, preserving inboxes. The account controller shares its predicate for sign-out confirmation. Each registered child is classified independently; existing parent-owned cancellation still applies to children whose lifetime is attached to a cancelled parent. The existing HTTP signal carries cancellation to transport.
Alternatives considered
A historical set of providers wrongly cancels a turn after it switches to an API-key route. Current settings misclassify an older in-flight request. A second provider field or module-global map duplicates information already recorded in request context. A login-level cancellation signal duplicates the existing Agent and HTTP cancellation chain.
Consequences
Model selection exposes both routes, and choosing an account route requires login even when an API key exists. The llm-deepseek-account and llm-deepseek-api-key plugins independently own catalogs, connection settings, and credentials; both use the llm-deepseek protocol library. Cancellation preserves queued input without waking it automatically. The recorded hook reason produces a localized conversation notice without changing durable event types.
Behavior tests cover credential separation, first preparation, tool-stage cancellation, and route replacement. The SDK account-provider-signout scenario boots the shipped profile and records interrupted output plus the cancellation cause.
中文
Problem
根据登录态选择凭证会改变现有提供方路由的计费身份。退登也需要停止依赖账号的任务,不能根据请求或工具运行期间可能已经改变的设置判断归属。
Decision
deepseek-official 和 deepseek-account 是独立路由,共享 DeepSeek 协议实现。每个适配器仅有一个凭证解析器和认证请求头模式。两条路由均不回退到另一凭证。账号服务保留登录决策定义的来源及签发方校验。
账号取消读取运行中 Agent 最近的 Session.requestContext(),不维护额外提供方字段。该已记录值在工具和重试阶段保留,随下一次绑定请求更新;空闲 Agent 不计入。新轮次首次准备期间,它仍可能指向上一轮的账号路由,因此退登也可能打断尚未绑定新请求的 API key 轮次。没有历史上下文的首请求若缺少账号凭据,会在传输前失败。
本地退登成功后发布账号事件。Platform 账号提供方安装账号模块的监听器,遍历 Agent 注册表,通过 Agent.cancel 取消匹配的账号路由并保留收件箱。账号控制器的退登确认复用同一判断函数。每个已注册子代理独立分类;生命周期绑定到已取消父代理的子代理仍受现有父级取消规则约束。现有 HTTP 信号将取消传递到传输层。
Alternatives considered
历史提供方集合会在轮次切换到 API Key 路由后仍错误取消它。当前设置会误判更早的在途请求。额外的提供方字段或模块级全局映射重复保存请求上下文中已有的信息。登录级取消信号重复现有 Agent 与 HTTP 取消链路。
Consequences
模型选择展示两条路由,即使存在 API Key,选择账号路由仍要求登录。两个路由分别由 llm-deepseek-account 和 llm-deepseek-api-key 注册,拥有独立的模型目录与连接设置,共用 llm-deepseek 协议实现。取消保留排队输入,不自动唤醒。已记录的 hook 原因生成本地化对话提示,无须改变持久事件类型。
行为测试覆盖凭证分离、首请求准备、工具阶段取消及路由替换。SDK account-provider-signout 场景启动随附 profile,记录被中断的输出和取消原因。