Repository navigation
Replies: 2 comments
|
The error suggests that Session V4 is validating message provenance more strictly than the memory plugin currently expects. Since the failure happens when dsh-hindsight-memory is enabled and the normal message is otherwise valid, I’d inspect the message that the plugin injects during autoRecall. The important question is whether the plugin creates a new message/source object without assigning a source kind owned by the producer. I’d compare:
If the plugin is constructing a synthetic message, it likely needs to use the Session V4 API for creating producer-owned content rather than manually constructing an object that happens to look like a message. I would avoid simply disabling the V4 validation because that could hide malformed session data. A good regression test would enable autoRecall, send a normal message, and verify that the resulting memory-injected content passes Session V4 validation and survives session serialization/reload. If this clears up the issue, please consider marking the answer as accepted so others who run into the same problem can find the solution more easily. |
|
Thanks for the write-up — the diagnosis is right, and the one-line fix is the right one. Two The admission is not a whitelist
if (!isSessionFormatJsonObject(value) || typeof value['kind'] !== 'string'
|| value['kind'].length === 0 || value['kind'] === 'plugin') {
throw new SessionFormatError('format v4 message requires a producer-owned source kind')
}So: not an object, The list you are thinking of is real, but it lives on a different path. Worth knowing, since it changes what "correct" means for a first-party-looking name: for a name in Which check actually refuses you, and why its message is emptyYou are right that it is the row gate, but the two source checks are not the same one. and re-checks a message only when Two consequences. Your recall block arrives as That is also why the sentence you saw names nothing: it is raised while decoding a physical row, and A plugin that closes the attribution gapI published It observes the committed event on with Two honest limits, since they bound what the plugin is worth to you: it does not rewrite anything — On the fixYour minimal fix is correct as written. Point 1 of the permanent fix — canonicalising |
Uh oh!
There was an error while loading. Please reload this page.
环境
复现步骤
观察到的错误
UI 直接显示底层错误文本:
session 日志末尾会出现:
removedCount:1, inserted:[] 之后没有任何 step事件,说明 recall 块进入 preStep waterfall 后被拦下。
根因
lib/index.js 的 agent/pre-step 监听器在 recall 命中时构造的 user message:
kind: "plugin" 是 V3 时代的语法。V4 把 kind: "plugin" 升级为「producer-owned」归属模型,要求 kind 是具体产方名(白名单如 tmux-context / time-context / session-reference 等,或 plugin: 形式)。
packages/session/session-format-v3-to-v4/src/message-sources.ts:9 的 source() 检查:
由于 recall 块通过 prepend: true 排在 waterfall 最前,一旦被构造就会被 assistant/call / tool/result 写日志的 admission gate(assertV4SourceRowAdmission)拦下,导致整轮失败。
参考对比:
最小修复
lib/index.js 第 338 行(一行):
修完后 recall 块用 plugin:hindsight-memory 作为 source kind,符合 V4 admission。已在我本地验证:line 338 改完后(node_modules 内的临时修复),重启 dsh,新一轮 step 1 正常进入 model call,无 admission error。
建议永久修复
考虑到 lib 是 build 产物,建议:
用户侧临时 workaround(如果等不及 release)
pnpm install 之后记得重打。
All reactions