You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by as...@apache.org on 2026/08/26 14:57:57 UTC

(maka) 06/26: refactor(desktop): separate message admission from exact turns

This is an automated email from the ASF dual-hosted git repository.

Astro-Han pushed a commit to branch fix/canonical-message-projection
in repository https://gitbox.apache.org/repos/asf/maka.git

commit da2a2fac59f1554f2dc0297e02c03c0970f4b50d
Author: AstroHan <le...@outlook.com>
AuthorDate: Wed Aug 26 04:25:42 2026 +0800

    refactor(desktop): separate message admission from exact turns
    
    Generated-by: Codex
---
 .../workhub-coordination-host-scope.test.ts        |  25 -----
 apps/desktop/src/preload/bridge-contract.d.ts      |  62 +++++++----
 apps/desktop/src/preload/preload.ts                | 115 +++++++++------------
 .../desktop/src/renderer/app-shell-chat-actions.ts |  36 +++++--
 .../platform/desktop/create-workbar-services.ts    |   8 +-
 .../renderer/workhub-coordination-host-scope.ts    |  31 +-----
 6 files changed, 119 insertions(+), 158 deletions(-)

diff --git a/apps/desktop/src/main/__tests__/workhub-coordination-host-scope.test.ts b/apps/desktop/src/main/__tests__/workhub-coordination-host-scope.test.ts
index 3f65c2e55..0a4e014fe 100644
--- a/apps/desktop/src/main/__tests__/workhub-coordination-host-scope.test.ts
+++ b/apps/desktop/src/main/__tests__/workhub-coordination-host-scope.test.ts
@@ -122,31 +122,6 @@ test('WorkHub candidates follow the resolved Coordination Session Host only', as
   stop();
 });
 
-test('WorkHub rejects an ordinary message admission at its exact Turn adapter', async () => {
-  const sessionId = desktopSessionKey({ hostId: 'host-a', sessionId: 'ordinary-a' });
-  const sessions = scopeWorkHubSessionsToCoordinationHost(
-    {
-      list: async () => [ordinarySession(sessionId)],
-      listTurns: async () => [],
-      create: async () => ordinarySession(sessionId),
-      send: async () => ({
-        ok: true,
-        disposition: 'steering',
-        messageId: 'message-1',
-      }),
-      stop: async () => undefined,
-      subscribeChanges: () => () => undefined,
-    },
-    { sessionId, isCurrent: () => true },
-    async () => ordinarySession(sessionId),
-  );
-
-  await assert.rejects(
-    sessions.send(sessionId, { type: 'send', turnId: 'turn-1', text: 'coordinate' }),
-    /ordinary message admission/,
-  );
-});
-
 function ordinarySession(id: string): Awaited<ReturnType<WorkHubDesktopSessionBridge['list']>>[number] {
   return {
     id,
diff --git a/apps/desktop/src/preload/bridge-contract.d.ts b/apps/desktop/src/preload/bridge-contract.d.ts
index 1afdfe448..57cbbacdb 100644
--- a/apps/desktop/src/preload/bridge-contract.d.ts
+++ b/apps/desktop/src/preload/bridge-contract.d.ts
@@ -801,25 +801,22 @@ export interface MakaBridge {
       completeHostIds: string[];
     }>;
     create(input?: CreateSessionRequestInput): Promise<DesktopSessionSummary>;
-    send(
+    submitMessage(
       sessionId: string,
-      command:
-        | SessionCommand
-          | {
-            type: 'send';
-            messageId?: string;
-            turnId?: string;
-            text: string;
-            displayText?: string;
-            skillIds?: string[];
-            attachmentItems?: RendererIngestInput[];
-            retainedAttachments?: import('@maka/core/events').AttachmentRef[];
-            turnOrchestration?: TurnOrchestration;
-            quotes?: import('@maka/core/events').QuoteRef[];
-            workspaceFileReferences?: Array<
-              Pick<import('@maka/core/events').InlineReference, 'value' | 'start'>
-            >;
-          },
+      command: {
+        type: 'send';
+        messageId: string;
+        text: string;
+        displayText?: string;
+        skillIds?: string[];
+        attachmentItems?: RendererIngestInput[];
+        retainedAttachments?: import('@maka/core/events').AttachmentRef[];
+        turnOrchestration?: never;
+        quotes?: import('@maka/core/events').QuoteRef[];
+        workspaceFileReferences?: Array<
+          Pick<import('@maka/core/events').InlineReference, 'value' | 'start'>
+        >;
+      },
     ): Promise<
       | {
           ok: true;
@@ -830,6 +827,35 @@ export interface MakaBridge {
           inlineReferences: import('@maka/core/events').InlineReference[];
           skillInvocation: import('@maka/runtime/skill-invocation').SkillInvocationResult;
         }
+      | {
+          ok: false;
+          reason: 'skill_invocation_failed';
+          skillInvocation: import('@maka/runtime/skill-invocation').SkillInvocationResult;
+        }
+      | {
+          ok: false;
+          reason: 'outcome_unknown';
+          messageId: string;
+          skillInvocation: import('@maka/runtime/skill-invocation').SkillInvocationResult;
+        }
+    >;
+    send(
+      sessionId: string,
+      command: {
+        type: 'send';
+        turnId: string;
+        text: string;
+        displayText?: string;
+        skillIds?: string[];
+        attachmentItems?: RendererIngestInput[];
+        retainedAttachments?: import('@maka/core/events').AttachmentRef[];
+        turnOrchestration?: TurnOrchestration;
+        quotes?: import('@maka/core/events').QuoteRef[];
+        workspaceFileReferences?: Array<
+          Pick<import('@maka/core/events').InlineReference, 'value' | 'start'>
+        >;
+      },
+    ): Promise<
       | {
           ok: true;
           turnId: string;
diff --git a/apps/desktop/src/preload/preload.ts b/apps/desktop/src/preload/preload.ts
index ae313ebd1..d646d8aa1 100644
--- a/apps/desktop/src/preload/preload.ts
+++ b/apps/desktop/src/preload/preload.ts
@@ -854,6 +854,47 @@ async function createDesktopSessionOnScope(
   return projectSessionSummary(scope, session);
 }
 
+function sendDesktopSessionCommand(
+  sessionId: string,
+  command: Parameters<MakaBridge['sessions']['submitMessage']>[1],
+): ReturnType<MakaBridge['sessions']['submitMessage']>;
+function sendDesktopSessionCommand(
+  sessionId: string,
+  command: Parameters<MakaBridge['sessions']['send']>[1],
+): ReturnType<MakaBridge['sessions']['send']>;
+async function sendDesktopSessionCommand(
+  sessionId: string,
+  command:
+    | Parameters<MakaBridge['sessions']['submitMessage']>[1]
+    | Parameters<MakaBridge['sessions']['send']>[1],
+): Promise<
+  | Awaited<ReturnType<MakaBridge['sessions']['submitMessage']>>
+  | Awaited<ReturnType<MakaBridge['sessions']['send']>>
+> {
+  const session = await runtimeHostSessionRef(sessionId);
+  const send = async (input: SessionCommand | Record<string, unknown>) => {
+    const result = (await ipcRenderer.invoke(
+      'sessions:send',
+      session.scope,
+      session.sessionId,
+      input,
+    )) as
+      | Awaited<ReturnType<MakaBridge['sessions']['submitMessage']>>
+      | Awaited<ReturnType<MakaBridge['sessions']['send']>>;
+    return result.ok
+      ? {
+          ...result,
+          attachments: projectDesktopAttachmentRefs(session.scope, result.attachments),
+        }
+      : result;
+  };
+  if (command.type === 'send' && 'attachmentItems' in command && command.attachmentItems) {
+    const encoded = await encodeIngestItems(command.attachmentItems as RendererIngestInput[]);
+    return send({ ...command, attachmentItems: encoded });
+  }
+  return send(command);
+}
+
 function sendActiveRuntimeHost(channel: string, ...args: unknown[]): void {
   void activeRuntimeHostRef()
     .then((scope) => ipcRenderer.send(channel, scope, ...args))
@@ -1644,75 +1685,11 @@ const makaBridge = {
       const scope = await activeRuntimeHostRef();
       return createDesktopSessionOnScope(scope, input);
     },
-    async send(
-      sessionId: string,
-      command:
-        | SessionCommand
-          | {
-            type: 'send';
-            messageId?: string;
-            turnId?: string;
-            text: string;
-            displayText?: string;
-            skillIds?: string[];
-            attachmentItems?: RendererIngestInput[];
-            retainedAttachments?: AttachmentRef[];
-            turnOrchestration?: TurnOrchestration;
-            quotes?: QuoteRef[];
-            workspaceFileReferences?: Array<Pick<InlineReference, 'value' | 'start'>>;
-          },
-    ): Promise<
-      | {
-          ok: true;
-          disposition: 'turn_started' | 'steering' | 'followup';
-          messageId: string;
-          turnId?: string;
-          attachments: AttachmentRef[];
-          inlineReferences: InlineReference[];
-          skillInvocation: import('@maka/runtime/skill-invocation').SkillInvocationResult;
-        }
-      | {
-          ok: true;
-          turnId: string;
-          attachments: AttachmentRef[];
-          inlineReferences: InlineReference[];
-          skillInvocation: import('@maka/runtime/skill-invocation').SkillInvocationResult;
-        }
-      | {
-          ok: false;
-          reason: 'skill_invocation_failed';
-          skillInvocation: import('@maka/runtime/skill-invocation').SkillInvocationResult;
-        }
-      | {
-          ok: false;
-          reason: 'outcome_unknown';
-          messageId: string;
-          skillInvocation: import('@maka/runtime/skill-invocation').SkillInvocationResult;
-        }
-    > {
-      const session = await runtimeHostSessionRef(sessionId);
-      const send = async (input: SessionCommand | Record<string, unknown>) => {
-        const result = await ipcRenderer.invoke(
-          'sessions:send',
-          session.scope,
-          session.sessionId,
-          input,
-        ) as Awaited<ReturnType<MakaBridge['sessions']['send']>>;
-        return result.ok
-          ? {
-              ...result,
-              attachments: projectDesktopAttachmentRefs(session.scope, result.attachments),
-            }
-          : result;
-      };
-      if (command.type === 'send' && 'attachmentItems' in command && command.attachmentItems) {
-        const encoded = await encodeIngestItems(command.attachmentItems as RendererIngestInput[]);
-        return send({
-          ...command,
-          attachmentItems: encoded,
-        });
-      }
-      return send(command);
+    submitMessage(sessionId, command) {
+      return sendDesktopSessionCommand(sessionId, command);
+    },
+    send(sessionId, command) {
+      return sendDesktopSessionCommand(sessionId, command);
     },
     compact(sessionId: string): Promise<OperationOutput<'context.compact'>> {
       return invokeSessionRuntimeHost('sessions:compact', sessionId);
diff --git a/apps/desktop/src/renderer/app-shell-chat-actions.ts b/apps/desktop/src/renderer/app-shell-chat-actions.ts
index ecd8b5864..1af50bf4e 100644
--- a/apps/desktop/src/renderer/app-shell-chat-actions.ts
+++ b/apps/desktop/src/renderer/app-shell-chat-actions.ts
@@ -388,12 +388,10 @@ export function createAppShellChatActions(deps: {
           pending && pending.length > 0
             ? retainedAttachmentRefs(pending)
             : undefined;
-        const sendResult = await window.maka.sessions.send(session.id, {
-          type: 'send',
-          ...(options.turnOrchestration ? { turnId: messageId } : { messageId }),
+        const sendCommand = {
+          type: 'send' as const,
           text,
           ...(options.displayText ? { displayText: options.displayText } : {}),
-          ...(options.turnOrchestration ? { turnOrchestration: options.turnOrchestration } : {}),
           ...(attachmentItems && attachmentItems.length > 0 ? { attachmentItems } : {}),
           ...(retainedAttachments && retainedAttachments.length > 0
             ? { retainedAttachments }
@@ -402,7 +400,17 @@ export function createAppShellChatActions(deps: {
           ...(options.workspaceFileReferences && options.workspaceFileReferences.length > 0
             ? { workspaceFileReferences: [...options.workspaceFileReferences] }
             : {}),
-        });
+        };
+        const sendResult = options.turnOrchestration
+          ? await window.maka.sessions.send(session.id, {
+              ...sendCommand,
+              turnId: messageId,
+              turnOrchestration: options.turnOrchestration,
+            })
+          : await window.maka.sessions.submitMessage(session.id, {
+              ...sendCommand,
+              messageId,
+            });
         if (!sendResult.ok) {
           if (sendResult.reason === 'outcome_unknown') {
             unsentSessionId = undefined;
@@ -494,12 +502,10 @@ export function createAppShellChatActions(deps: {
         pending && pending.length > 0
           ? retainedAttachmentRefs(pending)
           : undefined;
-      const sendResult = await window.maka.sessions.send(sessionId, {
-        type: 'send',
-        ...(options.turnOrchestration ? { turnId: messageId } : { messageId }),
+      const sendCommand = {
+        type: 'send' as const,
         text,
         ...(options.displayText ? { displayText: options.displayText } : {}),
-        ...(options.turnOrchestration ? { turnOrchestration: options.turnOrchestration } : {}),
         ...(attachmentItems && attachmentItems.length > 0 ? { attachmentItems } : {}),
         ...(retainedAttachments && retainedAttachments.length > 0
           ? { retainedAttachments }
@@ -508,7 +514,17 @@ export function createAppShellChatActions(deps: {
         ...(options.workspaceFileReferences && options.workspaceFileReferences.length > 0
           ? { workspaceFileReferences: [...options.workspaceFileReferences] }
           : {}),
-      });
+      };
+      const sendResult = options.turnOrchestration
+        ? await window.maka.sessions.send(sessionId, {
+            ...sendCommand,
+            turnId: messageId,
+            turnOrchestration: options.turnOrchestration,
+          })
+        : await window.maka.sessions.submitMessage(sessionId, {
+            ...sendCommand,
+            messageId,
+          });
       if (!sendResult.ok) {
         if (sendResult.reason === 'outcome_unknown') return true;
         removeOptimisticUserMessage(sessionId, messageId);
diff --git a/apps/desktop/src/renderer/platform/desktop/create-workbar-services.ts b/apps/desktop/src/renderer/platform/desktop/create-workbar-services.ts
index 9a342118e..2cfd56a22 100644
--- a/apps/desktop/src/renderer/platform/desktop/create-workbar-services.ts
+++ b/apps/desktop/src/renderer/platform/desktop/create-workbar-services.ts
@@ -119,13 +119,7 @@ export function createDesktopWorkbarServices(
         bridge.sessions.cleanupSessionCopy(sessionId),
       abandonSessionCopy: (sourceSessionId, copyId) =>
         bridge.sessions.abandonSessionCopy(sourceSessionId, copyId),
-      send: async (sessionId, command) => {
-        const result = await bridge.sessions.send(sessionId, command);
-        if (result.ok && 'disposition' in result) {
-          throw new Error('Side Conversation send crossed the ordinary message adapter');
-        }
-        return result;
-      },
+      send: (sessionId, command) => bridge.sessions.send(sessionId, command),
       stop: (sessionId, target) =>
         bridge.sessions.stop(
           sessionId,
diff --git a/apps/desktop/src/renderer/workhub-coordination-host-scope.ts b/apps/desktop/src/renderer/workhub-coordination-host-scope.ts
index 84ad982a4..55ebdb1c9 100644
--- a/apps/desktop/src/renderer/workhub-coordination-host-scope.ts
+++ b/apps/desktop/src/renderer/workhub-coordination-host-scope.ts
@@ -29,16 +29,9 @@ export interface WorkHubCoordinationHostAuthority {
   readonly isCurrent: () => boolean;
 }
 
-type WorkHubDesktopSessionSourceBridge = Omit<WorkHubDesktopSessionBridge, 'send'> & {
-  send(
-    sessionId: string,
-    command: { type: 'send'; turnId: string; text: string },
-  ): Promise<unknown>;
-};
-
 /** Restricts the transitional WorkHub router to the Coordination Session's Host. */
 export function scopeWorkHubSessionsToCoordinationHost(
-  sessions: WorkHubDesktopSessionSourceBridge,
+  sessions: WorkHubDesktopSessionBridge,
   coordination: WorkHubCoordinationHostAuthority,
   createOnCoordinationHost: WorkHubCoordinationHostSessionCreator,
 ): WorkHubDesktopSessionBridge {
@@ -87,27 +80,7 @@ export function scopeWorkHubSessionsToCoordinationHost(
     },
     async send(sessionId: string, command: { type: 'send'; turnId: string; text: string }) {
       requireTargetHost(sessionId);
-      const result = await sessions.send(sessionId, command);
-      if (!result || typeof result !== 'object' || !('ok' in result)) {
-        throw new Error('WorkHub exact Turn send returned an invalid result');
-      }
-      if (result.ok === false && 'reason' in result && typeof result.reason === 'string') {
-        return { ok: false as const, reason: result.reason };
-      }
-      if (
-        result.ok === true &&
-        !('disposition' in result) &&
-        'turnId' in result &&
-        typeof result.turnId === 'string' &&
-        (!('steered' in result) || result.steered === true)
-      ) {
-        return {
-          ok: true as const,
-          turnId: result.turnId,
-          ...('steered' in result ? { steered: true as const } : {}),
-        };
-      }
-      throw new Error('WorkHub exact Turn send returned an ordinary message admission');
+      return sessions.send(sessionId, command);
     },
     async stop(
       sessionId: string,


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org