From 7453b84096555990eb0a7a682a63ea921787439a Mon Sep 17 00:00:00 2001 From: jiang Date: Wed, 2 Sep 2026 19:06:47 +0800 Subject: [PATCH] fix(dsh): support old and new conversation APIs --- .../deepseek-harness/tests/target.test.ts | 55 ++++++++++++++++++- .../memmy-deepseek-harness-plugin.ts | 12 +++- .../memmy-deepseek-harness-plugin.ts | 12 +++- 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/App/backend/src/adapters/outbound/skill-writer/deepseek-harness/tests/target.test.ts b/App/backend/src/adapters/outbound/skill-writer/deepseek-harness/tests/target.test.ts index b206152bc..ad341a563 100644 --- a/App/backend/src/adapters/outbound/skill-writer/deepseek-harness/tests/target.test.ts +++ b/App/backend/src/adapters/outbound/skill-writer/deepseek-harness/tests/target.test.ts @@ -124,8 +124,14 @@ describe("DeepSeek Harness skill target", () => { expect(handoff?.id).toBe("@memmy/memmy-memory"); let definition: Record | undefined; - handoff?.factory().apply({ - conversationEvents: { register: (value: Record) => { definition = value; } } + const client = handoff?.factory(); + expect(client?.inject).toEqual([]); + client?.apply({ + get(name: string) { + return name === "conversationEvents" + ? { register: (value: Record) => { definition = value; } } + : undefined; + } }); const message = { id: "user-1", @@ -164,6 +170,51 @@ describe("DeepSeek Harness skill target", () => { }); }); + it("prefers the uiConversation event registry when both APIs are available", async () => { + const rootDirectory = createRoot(); + const target = createDeepseekHarnessSkillTarget({ rootDirectory }); + await target.installPlugin?.("deepseek_harness"); + const clientPath = join(installedPluginDirectory(rootDirectory), "client.js"); + let handoff: { id: string; factory(): Record } | undefined; + runInNewContext(readFileSync(clientPath, "utf8"), { + window: { __ModuleLoader__: { load: (value: typeof handoff) => { handoff = value; } } } + }); + + let modernRegistrations = 0; + let legacyRegistrations = 0; + const client = handoff?.factory(); + client?.apply({ + get(name: string) { + if (name === "uiConversation") { + return { events: { register: () => { modernRegistrations += 1; } } }; + } + if (name === "conversationEvents") { + return { register: () => { legacyRegistrations += 1; } }; + } + return undefined; + } + }); + + expect(modernRegistrations).toBe(1); + expect(legacyRegistrations).toBe(0); + }); + + it("fails clearly when neither conversation event API is available", async () => { + const rootDirectory = createRoot(); + const target = createDeepseekHarnessSkillTarget({ rootDirectory }); + await target.installPlugin?.("deepseek_harness"); + const clientPath = join(installedPluginDirectory(rootDirectory), "client.js"); + let handoff: { id: string; factory(): Record } | undefined; + runInNewContext(readFileSync(clientPath, "utf8"), { + window: { __ModuleLoader__: { load: (value: typeof handoff) => { handoff = value; } } } + }); + + const client = handoff?.factory(); + expect(() => client?.apply({ get: () => undefined })).toThrow( + "memmy-memory requires uiConversation.events or conversationEvents" + ); + }); + it("replaces legacy versioned patch markers", async () => { const rootDirectory = createRoot(); const patchPath = join(rootDirectory, "cordis.patch.yml"); diff --git a/App/backend/src/adapters/outbound/skill-writer/templates/memmy-deepseek-harness-plugin.ts b/App/backend/src/adapters/outbound/skill-writer/templates/memmy-deepseek-harness-plugin.ts index 5d1cad190..7e8264299 100644 --- a/App/backend/src/adapters/outbound/skill-writer/templates/memmy-deepseek-harness-plugin.ts +++ b/App/backend/src/adapters/outbound/skill-writer/templates/memmy-deepseek-harness-plugin.ts @@ -527,10 +527,18 @@ export const DEEPSEEK_HARNESS_PLUGIN_CLIENT = String.raw`window.__ModuleLoader__ const exports = module.exports; const name = "memmy-memory-client"; - const inject = ["conversationEvents"]; + const inject = []; + + function resolveConversationEventRegistry(ctx) { + const uiConversation = ctx.get("uiConversation"); + if (uiConversation && uiConversation.events) return uiConversation.events; + const conversationEvents = ctx.get("conversationEvents"); + if (conversationEvents) return conversationEvents; + throw new Error("memmy-memory requires uiConversation.events or conversationEvents"); + } function apply(ctx) { - ctx.conversationEvents.register({ + resolveConversationEventRegistry(ctx).register({ kind: "memmy-optimistic-user", target: "chat", match(event) { diff --git a/Memory/src/agent-source/integration/templates/memmy-deepseek-harness-plugin.ts b/Memory/src/agent-source/integration/templates/memmy-deepseek-harness-plugin.ts index 5d1cad190..7e8264299 100644 --- a/Memory/src/agent-source/integration/templates/memmy-deepseek-harness-plugin.ts +++ b/Memory/src/agent-source/integration/templates/memmy-deepseek-harness-plugin.ts @@ -527,10 +527,18 @@ export const DEEPSEEK_HARNESS_PLUGIN_CLIENT = String.raw`window.__ModuleLoader__ const exports = module.exports; const name = "memmy-memory-client"; - const inject = ["conversationEvents"]; + const inject = []; + + function resolveConversationEventRegistry(ctx) { + const uiConversation = ctx.get("uiConversation"); + if (uiConversation && uiConversation.events) return uiConversation.events; + const conversationEvents = ctx.get("conversationEvents"); + if (conversationEvents) return conversationEvents; + throw new Error("memmy-memory requires uiConversation.events or conversationEvents"); + } function apply(ctx) { - ctx.conversationEvents.register({ + resolveConversationEventRegistry(ctx).register({ kind: "memmy-optimistic-user", target: "chat", match(event) {