Replies: 1 comment
|
补充:这个问题在上游已经有独立修复,原帖的分析针对的是旧代码,仅供追溯。 我最初反馈时基于的提交是 拉取最新 master( const REMOTE_METHOD_DESCRIPTOR = '@deepseek-ai/dsh-typert-protocol/remote-methods'
相比之下,我原帖附的补丁(把标记表挂到 原帖正文与 fork 分支( 最后一句排查提醒仍然成立:模块解析路径相同 ≠ 模块实例相同。判断「同一个包是否被加载了多份」必须比对模块对象本身,不能只信 |
Uh oh!
There was an error while loading. Please reload this page.
装在 profile 里的第三方插件导出的 Typert Remote 方法全部不可用:所有
/api/<namespace>/<method>请求返回 HTTP 404,而提供这些方法的 Service 已挂载且处于 ACTIVE。复现、预期与验收
@daweifu/capability-menu-web:其CapabilityPolicyGateway继承TypertRemoteService,用@Remote装饰getConfig/updateConfig/classifyAll,服务键capabilityPolicyGateway,wire namespacecapabilityPolicy)dsh web)/api/capabilityPolicy/classifyAllimpl[capabilityPolicyGateway]state=ACTIVE、typertRemote.namespace=capabilityPolicy,但网关的collectSrcClaims()不为它认领任何端点。同一宿主上工作区内的包(如pluginInventory)返回 200。remoteMethods(),都能读到另一副本由Remote装饰器写入的标记/api/capabilityPolicy/classifyAll返回 200 而非 404根因
@deepseek-ai/dsh-typert-protocol在一次运行中被加载成两个模块实例:宿主(工作区源码模式)解析到packages/typert/protocol/src/index.ts,而装在 profilenode_modules里的第三方包解析到包exports的./lib/index.js。Remote装饰器通过mark()把方法标记写进一张模块私有的WeakMap(packages/typert/protocol/src/index.ts,修改前 L155),remoteMethods()再从这张表读。两份实例 = 两张互不相通的表,于是网关的collectSrcClaims()(packages/api/gateway/src/index.tsL279-294)对第三方服务读到空方法列表,不认领任何端点。一个排查陷阱:
import.meta.resolve对两个导入方都返回src/index.ts,但两个模块对象并不相同 —— 解析路径不能作为模块实例同一性的证据。修复
把标记表挂到
globalThis的Symbol.for('dsh.typert.remoteMarkers')上,使所有副本共享一张表(与vendor/cordis/src/context.ts用Symbol.for('cordis.is')跨副本的做法一致)。标记仍以 prototype 为键保存在WeakMap中,因此不会在第三方类上新增属性,条目随其所属类消亡。补丁(1 个提交,含跨副本回归测试与 Agent Note):
https://github.com/fishOfOUC/deepseek-harness/tree/fix/typert-remote-marker-table-global
由于本仓库不接受 PR,未能直接提交,在此附上根因与补丁位置供参考。
All reactions