diff --git a/src/trader/acp-transport.ts b/src/trader/acp-transport.ts index 40a0135..d65215a 100644 --- a/src/trader/acp-transport.ts +++ b/src/trader/acp-transport.ts @@ -10,7 +10,7 @@ * Mirror of trader-service/src/cli/dm-transport.ts. */ -import type { DirectMessage } from '@unicitylabs/sphere-sdk'; +import type { DirectMessage, SendMessageOptions } from '@unicitylabs/sphere-sdk'; import { createAcpMessage, @@ -30,7 +30,11 @@ export type { TimeoutError, TransportError }; export { MIN_TIMEOUT_MS }; export interface SphereComms { - sendDM(recipient: string, content: string): Promise<{ recipientPubkey: string }>; + sendDM( + recipient: string, + content: string, + options?: SendMessageOptions, + ): Promise<{ recipientPubkey: string }>; onDirectMessage(handler: (message: DirectMessage) => void): () => void; } @@ -165,7 +169,12 @@ class AcpDmTransportImpl implements AcpDmTransport { return; } - this.comms.sendDM(this.tenantAddress, payload).then((sent) => { + // sphere-sdk#559 / PR #558 — ACP RPC is short-lived (the trader + // CLI's `sphere trader ` exits as soon as the result + // lands). Skip the self-wrap so we don't leave a copy of every + // outgoing ACP command in the relay's `#p:controller` index for + // the next short-lived CLI process to pull down on subscribe. + this.comms.sendDM(this.tenantAddress, payload, { selfWrap: false }).then((sent) => { if (!this.resolvedPubkey) { this.resolvedPubkey = normalizeKey(sent.recipientPubkey); // Drain pre-resolution buffer. diff --git a/src/transport/dm-transport.ts b/src/transport/dm-transport.ts index 79bc99f..0d97711 100644 --- a/src/transport/dm-transport.ts +++ b/src/transport/dm-transport.ts @@ -13,7 +13,7 @@ * }); */ -import type { DirectMessage } from '@unicitylabs/sphere-sdk'; +import type { DirectMessage, SendMessageOptions } from '@unicitylabs/sphere-sdk'; import type { HmcpRequest, HmcpResponse } from './hmcp-types.js'; import { parseHmcpResponse, byteLength, MAX_MESSAGE_SIZE } from './hmcp-types.js'; import { TimeoutError, TransportError } from './errors.js'; @@ -47,7 +47,11 @@ export interface DmTransportConfig { /** Narrow slice of Sphere.communications needed by DmTransport — injectable for testing. */ export interface SphereComms { - sendDM(recipient: string, content: string): Promise<{ recipientPubkey: string }>; + sendDM( + recipient: string, + content: string, + options?: SendMessageOptions, + ): Promise<{ recipientPubkey: string }>; onDirectMessage(handler: (message: DirectMessage) => void): () => void; } @@ -286,7 +290,12 @@ class DmTransportImpl implements DmTransport { `Request too large: ${byteLength(serialized)} bytes exceeds MAX_MESSAGE_SIZE (${MAX_MESSAGE_SIZE})`, ); } - const sent = await this.comms.sendDM(this.managerAddress, serialized); + // sphere-sdk#559 / PR #558 — HMCP RPC is short-lived (CLI exits + // shortly after the manager's reply). Suppressing the self-wrap + // halves the per-process relay-index pollution targeting the + // controller pubkey, which directly reduces the §3/§4 buffered- + // event noise the F1 soak measured at ~7 new events per spawn. + const sent = await this.comms.sendDM(this.managerAddress, serialized, { selfWrap: false }); // Cache the resolved pubkey on first send. Subsequent sends for the same // manager address produce the same pubkey, so concurrent writes are safe. if (!this.resolvedPubkey) {