Skip to content

Fix #2538: [memos-local-plugin] dsh 0.2.x session format V4 rejects plugin messages: "produ - #2541

Open
Memtensor-AI wants to merge 1 commit into
MemTensor:dev-v2.0.36from
Memtensor-AI:bugfix/autodev-2538-20261023114157826
Open

Memtensor-AI wants to merge 1 commit into
MemTensor:dev-v2.0.36from
Memtensor-AI:bugfix/autodev-2538-20261023114157826

Conversation

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

Description

Fixes #2538. The DeepSeek Harness adapter in apps/memos-local-plugin still wrote the retired V3 message source wrapper source: { kind: "plugin", plugin: "..." }. DSH session format V4 validates runtime writes (not only migrations), so the per-turn recall message injected at agent/pre-step was rejected before persistence with SessionFormatError: format v4 message requires a producer-owned source kind, failing every conversation turn with UNKNOWN. Both runtime writers — the recall message in adapters/deepseek-harness/index.ts and the host-LLM user message in host-llm.ts — now emit kind: "plugin:memos-local-memory" through a new shared adapters/deepseek-harness/source-kind.ts. That constant is declared in DSH's MessageSourceMap extension point (the same pattern first-party plugins use) rather than cast, and it is exactly the value DSH's own V3→V4 migration derives for memos-local-memory, so live and migrated messages stay indistinguishable. The recall message keeps form: "recall"; host-LLM messages still omit form, since those are auxiliary MemOS calls rather than DSH conversation context.

The secondary issue is also addressed: the optional DSH peer range stopped at <0.2.0, which made DSH 0.2.x silently skip the bundle at startup. Semver prerelease rules mean <0.2.0 does not admit 0.1.7-rc.x and <0.3.0 does not admit 0.2.1-rc.x, so the range now enumerates each V4 preview line that was actually compiled and tested. Dev dependencies move to DSH 0.2.1-rc.2 so CI exercises the V4 surface, and JsonValue (moved out of dsh-tools after 0.2) is declared locally so the adapter builds against both lines. Adapter README and CHANGELOG document the new source contract.

Verification is real and reproduced the issue's exact error: calling the published assertV4RowAdmission from @deepseek-ai/dsh-session-format-v3-to-v4@0.2.1-rc.2 rejects the V3 shape and admits both new shapes, including the constants exported by the compiled dist. tsc --noEmit passes and all 68 DSH adapter tests pass on DSH 0.1.0-rc.6, 0.1.7-rc.2, 0.2.0-rc.2 and 0.2.1-rc.2; the full plugin suite is 1601 passed / 2 skipped; npm run build succeeds. A new regression test fails if either writer or any adapter source reintroduces a code-level kind: "plugin".

Changes are committed as 1263b229 on bugfix/autodev-2538-20261023114157826 and pushed to the remote. The opsp task file and openspec change (proposal.md, spec.md, design.md, verification-report.md) were produced and archived to the specs repository. No PR was opened from here, per the scheduler contract.

Related Issue (Required): Fixes #2538

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g. code style improvements, linting)
  • Documentation update

How Has This Been Tested?

Automated tests are pending.

  • Unit Test
  • Test Script Or Test Steps (please provide)
  • Pipeline Automated API Test (please provide)

Checklist

  • I have performed a self-review of my own code
  • I have commented my code in hard-to-understand areas
  • I have added tests that prove my fix is effective or that my feature works
  • I have created related documentation issue/PR in MemOS-Docs (if applicable)
  • I have linked the issue to this PR (if applicable)
  • I have mentioned the person who will review this PR

@whipser030, @hijzy please review this PR.

Reviewer Checklist

DSH session format V4 validates runtime writes, not just migrations, and
rejects any message whose source.kind is the retired V3 wrapper "plugin".
The DeepSeek Harness adapter still wrote that shape on both message paths,
so the recall injected before every turn failed agent/pre-step and each
turn surfaced as UNKNOWN.

Both writers now emit "plugin:memos-local-memory" through a shared
constant, declared in DSH's MessageSourceMap extension point. That is the
same kind DSH's own V3->V4 migration derives, so live and migrated
messages stay indistinguishable.

The optional DSH peer range also stopped at <0.2.0, which silently skips
the bundle on current hosts. It now enumerates each V4 preview line that
was actually compiled and tested. JsonValue, moved out of dsh-tools after
0.2, is declared locally so the adapter builds against both lines.

Verified: full plugin suite 1601 passed / 2 skipped; adapter suite 68
tests green on DSH 0.1.0-rc.6, 0.1.7-rc.2, 0.2.0-rc.2 and 0.2.1-rc.2;
shipped dist accepted by the real V4 admission validator.
@Memtensor-AI Memtensor-AI added ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Oct 23, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

🤖 Open Code Review

Target: PR #2541
Task: 2e1b2262c967d90d
Base: dev-v2.0.36
Head: bugfix/autodev-2538-20261023114157826
Head SHA: 1263b2290bc42059844f0b4670b270a0a35d671b

🔍 OpenCodeReview found 7 issue(s) in this PR.

⚠️ 1 warning(s) occurred during review.


1. apps/memos-local-plugin/adapters/deepseek-harness/source-kind.ts (L28-L30)

The augmentation repeats the plugin name as a hardcoded literal (both the map key and the kind member) instead of deriving it from DEEPSEEK_HARNESS_PLUGIN. An interface key cannot be a computed value, so the duplication is unavoidable — but nothing links the two: renaming DEEPSEEK_HARNESS_PLUGIN still compiles, while DEEPSEEK_HARNESS_SOURCE_KIND becomes plugin:<new>, which no longer matches a MessageSourceMap entry and silently stops type-checking createUserMessage calls that rely on the augmentation (the runtime value would keep writing an unregistered kind). Adding a compile-time assertion keeps the literal honest.


2. apps/memos-local-plugin/adapters/deepseek-harness/bridge.ts (L21)

bridge.ts states that it deliberately keeps DSH imports out so lifecycle logic stays independently testable and DSH types do not leak into the algorithm core, but this re-export pulls source-kind.ts — which imports from @deepseek-ai/dsh-llm and augments its MessageSourceMap module — into every module graph that touches the bridge. The augmentation is compile-time only, yet it now applies to all bridge consumers (including tests, where a source: { kind: "plugin" } literal previously type-checked). Consider re-exporting only DEEPSEEK_HARNESS_PLUGIN here and letting index.ts/host-llm.ts import DEEPSEEK_HARNESS_SOURCE_KIND from ./source-kind.js directly.


3. apps/memos-local-plugin/package.json (L139)

The new DSH 0.2.1-rc.2 packages peer-require @deepseek-ai/cordis: "~4.0.5", but this package still declares "@deepseek-ai/cordis": "^4.0.1" in devDependencies, and package-lock.json still resolves cordis to 4.0.1 — outside that ~4.0.5 range. That leaves an unsatisfiable peer graph for npm ci/npm install (ERESOLVE, or a second hoisted cordis copy). Since the adapter imports Context from @deepseek-ai/cordis, two instances would also break plugin mounting at runtime. Bump the cordis devDependency to ^4.0.5 alongside this bump and regenerate the lockfile.


4. apps/memos-local-plugin/package.json (L141)

pnpm-lock.yaml is also tracked for this package and was not updated here: its importer still pins the DSH packages at 0.1.0-rc.6 and has no dsh-sandbox/dsh-scope entries. Anyone running pnpm install --frozen-lockfile (or CI using pnpm) in apps/memos-local-plugin will now fail with an out-of-date-lockfile error. Regenerate both lockfiles, or drop the unused one so a single source of truth remains.


5. apps/memos-local-plugin/package.json (L103)

Careful before trimming this range: the second alternative >=0.1.7-rc.1 <0.2.0 is not redundant with the first under npm semver prerelease rules. A prerelease version only satisfies a comparator set if at least one comparator has the same major.minor.patch tuple and carries a prerelease tag. >=0.1.0-rc.5 <0.2.0 has comparators on tuple 0.1.0 and 0.2.0, so 0.1.7-rc.1 does not match it — only the explicit >=0.1.7-rc.1 comparator admits the 0.1.7-rc.x line that the CHANGELOG/README claim to support (0.1.7-rc.x, 0.2.0-rc.x, 0.2.1-rc.x). Deleting it would silently drop that line. Suggest keeping it and instead adding a short comment (or documenting in the README) that each alternative exists to admit the prereleases of a specific x.y.z tuple, so the repeated prefixes are intentional.


6. apps/memos-local-plugin/adapters/deepseek-harness/source-kind.ts (L24)

This writes the V4 producer-owned kind unconditionally, on every DSH version the adapter still advertises. package.json keeps >=0.1.0-rc.5 <0.2.0, so pre-V4 hosts (rc.5/rc.6, whose MessageSourceMap is keyed by kind: "plugin" with a sibling plugin field) now receive kind: "plugin:memos-local-memory" with no plugin field and no format-version gate. The file's own rationale only claims type compatibility across both surfaces — the augmentation simply adds an unused key, so tsc cannot catch a runtime rejection, and nothing here verifies that an unknown kind passes a pre-V4 validator. If those hosts validate source.kind strictly (unknown kind rejected, or source not renderable), recall and host-LLM messages regress on the very lines the peer range still admits — the mirror image of the bug this PR fixes.

Please confirm against the oldest advertised line (0.1.0-rc.5/rc.6) that a plugin:<name> kind is accepted, and if it is not, either gate the emitted shape on the detected session-format version or narrow the peer range to the V4 lines.


7. apps/memos-local-plugin/package.json (L107)

The last alternative >=0.2.1-rc.1 <0.3.0 admits every future stable 0.2.x minor (0.2.2, 0.2.5, ...), which is broader than the tested line the README documents (0.2.1-rc.x). Because these DSH packages pin exact versions among themselves, a later 0.2.x with a session-format change would be accepted here without allow-version and then fail at runtime — the same class of failure this fix addresses. Consider bounding it to the tested line, e.g. >=0.2.1-rc.1 <0.2.2, and widening deliberately when a new preview is validated.


🧹 Filtered 1 low-confidence OCR finding(s) before posting/fix-loop (duplicate: 1).

Generated by cloud-assistant via Open Code Review.

@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

🔧 Open Code Review requested Agent fix

Open Code Review found 7 issue(s). I have resumed the development Agent to fix them.

  • Task: 2e1b2262c967d90d
  • Fix attempt: 1/2
  • Finding delta: 0 repeated / 7 new / 0 likely resolved

The Agent will push a new commit to this PR branch. OCR will recheck after the commit is pushed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:in-progress Someone or AI is working on it | 人工或 AI 正在处理

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants