@bouncer-protocol/bouncer 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/index.js +20 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -115,9 +115,10 @@ interface OpenClawPluginToolContext {
|
|
|
115
115
|
}
|
|
116
116
|
interface AgentTool {
|
|
117
117
|
name: string;
|
|
118
|
+
label?: string;
|
|
118
119
|
description: string;
|
|
119
120
|
parameters?: Record<string, unknown>;
|
|
120
|
-
execute: (params: Record<string, unknown>,
|
|
121
|
+
execute: (toolCallId: string, params: Record<string, unknown>, signal?: AbortSignal, onUpdate?: unknown) => Promise<unknown>;
|
|
121
122
|
}
|
|
122
123
|
type OpenClawPluginToolFactory = (ctx: OpenClawPluginToolContext) => AgentTool | AgentTool[] | null | undefined;
|
|
123
124
|
interface OpenClawPluginApi {
|
package/dist/index.js
CHANGED
|
@@ -655,18 +655,18 @@ function createBrandTools(config, logger) {
|
|
|
655
655
|
}
|
|
656
656
|
}
|
|
657
657
|
},
|
|
658
|
-
async execute(params) {
|
|
658
|
+
async execute(_toolCallId, params) {
|
|
659
659
|
const lobby = getLobbyClient();
|
|
660
|
-
if (!lobby) return { error: "Not connected to lobby" };
|
|
660
|
+
if (!lobby) return { content: [{ type: "text", text: JSON.stringify({ error: "Not connected to lobby" }) }], details: {} };
|
|
661
661
|
try {
|
|
662
662
|
const result = await lobby.request(
|
|
663
663
|
{ type: "browse_bouncers", limit: params.limit ?? 20 },
|
|
664
664
|
"browse_bouncers_result"
|
|
665
665
|
);
|
|
666
666
|
logger.info(`[bouncer] Browse returned ${result.bouncers?.length ?? 0} bouncers`);
|
|
667
|
-
return result.bouncers;
|
|
667
|
+
return { content: [{ type: "text", text: JSON.stringify(result.bouncers) }], details: {} };
|
|
668
668
|
} catch (err) {
|
|
669
|
-
return { error: `Browse failed: ${err.message}` };
|
|
669
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: `Browse failed: ${err.message}` }) }], details: {} };
|
|
670
670
|
}
|
|
671
671
|
}
|
|
672
672
|
};
|
|
@@ -683,18 +683,18 @@ function createBrandTools(config, logger) {
|
|
|
683
683
|
},
|
|
684
684
|
required: ["bouncer_id"]
|
|
685
685
|
},
|
|
686
|
-
async execute(params) {
|
|
686
|
+
async execute(_toolCallId, params) {
|
|
687
687
|
const lobby = getLobbyClient();
|
|
688
|
-
if (!lobby) return { error: "Not connected to lobby" };
|
|
688
|
+
if (!lobby) return { content: [{ type: "text", text: JSON.stringify({ error: "Not connected to lobby" }) }], details: {} };
|
|
689
689
|
try {
|
|
690
690
|
const result = await lobby.request(
|
|
691
691
|
{ type: "get_profile", bouncer_id: params.bouncer_id },
|
|
692
692
|
"get_profile_result"
|
|
693
693
|
);
|
|
694
|
-
if (result.error) return { error: result.error };
|
|
695
|
-
return result.profile;
|
|
694
|
+
if (result.error) return { content: [{ type: "text", text: JSON.stringify({ error: result.error }) }], details: {} };
|
|
695
|
+
return { content: [{ type: "text", text: JSON.stringify(result.profile) }], details: {} };
|
|
696
696
|
} catch (err) {
|
|
697
|
-
return { error: `Profile fetch failed: ${err.message}` };
|
|
697
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: `Profile fetch failed: ${err.message}` }) }], details: {} };
|
|
698
698
|
}
|
|
699
699
|
}
|
|
700
700
|
};
|
|
@@ -731,19 +731,21 @@ function createBrandTools(config, logger) {
|
|
|
731
731
|
},
|
|
732
732
|
required: ["bouncer_id", "product", "terms", "opening_message", "priority_bid"]
|
|
733
733
|
},
|
|
734
|
-
async execute(params) {
|
|
734
|
+
async execute(_toolCallId, params) {
|
|
735
735
|
const lobby = getLobbyClient();
|
|
736
|
+
const wrap = (obj) => ({ content: [{ type: "text", text: JSON.stringify(obj) }], details: {} });
|
|
736
737
|
if (!lobby) {
|
|
737
738
|
logger.error("[bouncer] bouncer_offer: getLobbyClient() returned null \u2014 lobby not initialized");
|
|
738
|
-
return { error: "Not connected to lobby" };
|
|
739
|
+
return wrap({ error: "Not connected to lobby" });
|
|
739
740
|
}
|
|
740
741
|
const connected = lobby.isConnected();
|
|
741
742
|
logger.info(`[bouncer] bouncer_offer: lobby.isConnected() = ${connected}`);
|
|
742
743
|
if (!connected) {
|
|
743
744
|
logger.error("[bouncer] bouncer_offer: lobby exists but isConnected() is false \u2014 WS may be reconnecting");
|
|
744
|
-
return { error: "Lobby WS not connected \u2014 may be reconnecting. Try again in a few seconds." };
|
|
745
|
+
return wrap({ error: "Lobby WS not connected \u2014 may be reconnecting. Try again in a few seconds." });
|
|
745
746
|
}
|
|
746
747
|
const bouncerId = params.bouncer_id;
|
|
748
|
+
logger.info(`[bouncer] bouncer_offer PARAMS: ${JSON.stringify(params)}`);
|
|
747
749
|
try {
|
|
748
750
|
logger.info(`[bouncer] Submitting offer to ${bouncerId}`);
|
|
749
751
|
const sendStart = Date.now();
|
|
@@ -761,7 +763,7 @@ function createBrandTools(config, logger) {
|
|
|
761
763
|
);
|
|
762
764
|
logger.info(`[bouncer] submit_offer response in ${Date.now() - sendStart}ms`);
|
|
763
765
|
if (offerResult.error) {
|
|
764
|
-
return { error: `Offer submission failed: ${offerResult.error}` };
|
|
766
|
+
return wrap({ error: `Offer submission failed: ${offerResult.error}` });
|
|
765
767
|
}
|
|
766
768
|
const offerId = offerResult.offer_id;
|
|
767
769
|
logger.info(`[bouncer] Offer submitted: ${offerId}`);
|
|
@@ -771,25 +773,25 @@ function createBrandTools(config, logger) {
|
|
|
771
773
|
"create_negotiation_result"
|
|
772
774
|
);
|
|
773
775
|
if (negResult.error) {
|
|
774
|
-
return { error: `Negotiation creation failed: ${negResult.error}`, offer_id: offerId };
|
|
776
|
+
return wrap({ error: `Negotiation creation failed: ${negResult.error}`, offer_id: offerId });
|
|
775
777
|
}
|
|
776
778
|
const negotiationId = negResult.negotiation_id;
|
|
777
779
|
logger.info(`[bouncer] Negotiation created: ${negotiationId}`);
|
|
778
780
|
logger.info(`[bouncer] Waiting for bouncer to accept (via WS)...`);
|
|
779
781
|
const accepted = await waitForAcceptanceWS(negotiationId, 12e4);
|
|
780
782
|
if (!accepted) {
|
|
781
|
-
return { status: "declined_or_timeout", offer_id: offerId, negotiation_id: negotiationId };
|
|
783
|
+
return wrap({ status: "declined_or_timeout", offer_id: offerId, negotiation_id: negotiationId });
|
|
782
784
|
}
|
|
783
785
|
logger.info(`[bouncer] Accepted! Connecting to negotiation room...`);
|
|
784
786
|
await connectToNegotiationRoom(negotiationId, config, wsUrl(config.apiUrl), logger);
|
|
785
|
-
return {
|
|
787
|
+
return wrap({
|
|
786
788
|
status: "connected",
|
|
787
789
|
offer_id: offerId,
|
|
788
790
|
negotiation_id: negotiationId,
|
|
789
791
|
message: "Connected to negotiation room. Incoming messages will appear as chat messages."
|
|
790
|
-
};
|
|
792
|
+
});
|
|
791
793
|
} catch (err) {
|
|
792
|
-
return { error: `Offer flow failed: ${err.message}` };
|
|
794
|
+
return wrap({ error: `Offer flow failed: ${err.message}` });
|
|
793
795
|
}
|
|
794
796
|
}
|
|
795
797
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sdk-types.ts","../src/connector-parser.ts","../src/bouncer-channel.ts","../src/connector-lobby.ts","../src/connector-session.ts","../src/service.ts","../src/types.ts","../src/tools.ts","../index.ts"],"sourcesContent":["/**\n * Minimal type stubs for the OpenClaw Plugin SDK.\n *\n * When installed into an OpenClaw environment, replace these with:\n * import { definePluginEntry } from \"openclaw/plugin-sdk/core\";\n *\n * These stubs match the contract from openclaw/openclaw src/plugin-sdk/core.ts\n * and src/plugins/types.ts as of 2026-03.\n */\n\nexport interface PluginLogger {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n debug(msg: string, ...args: unknown[]): void;\n}\n\nexport interface ReplyPayload {\n text?: string;\n body?: string;\n mediaUrl?: string;\n mediaUrls?: string[];\n [key: string]: unknown;\n}\n\nexport interface MsgContext {\n Body?: string;\n BodyForAgent?: string;\n RawBody?: string;\n CommandBody?: string;\n From?: string;\n To?: string;\n SessionKey?: string;\n AccountId?: string;\n OriginatingChannel?: string;\n OriginatingTo?: string;\n ChatType?: string;\n SenderName?: string;\n SenderId?: string;\n Provider?: string;\n Surface?: string;\n ConversationLabel?: string;\n Timestamp?: number;\n CommandAuthorized?: boolean;\n [key: string]: unknown;\n}\n\nexport type FinalizedMsgContext = Omit<MsgContext, \"CommandAuthorized\"> & {\n CommandAuthorized: boolean;\n};\n\nexport interface ReplyDispatcherWithTypingOptions {\n deliver: (payload: ReplyPayload, info: { kind: string }) => Promise<void>;\n onReplyStart?: () => Promise<void> | void;\n onIdle?: () => void;\n onCleanup?: () => void;\n [key: string]: unknown;\n}\n\nexport interface DispatchInboundResult {\n [key: string]: unknown;\n}\n\nexport interface PluginRuntime {\n channel: {\n reply: {\n finalizeInboundContext: <T extends Record<string, unknown>>(ctx: T) => T & FinalizedMsgContext;\n dispatchReplyWithBufferedBlockDispatcher: (params: {\n ctx: MsgContext | FinalizedMsgContext;\n cfg: OpenClawConfig;\n dispatcherOptions: ReplyDispatcherWithTypingOptions;\n replyOptions?: Record<string, unknown>;\n }) => Promise<DispatchInboundResult>;\n dispatchReplyFromConfig?: (...args: unknown[]) => Promise<unknown>;\n };\n debounce: {\n createInboundDebouncer: (...args: unknown[]) => unknown;\n resolveInboundDebounceMs: (...args: unknown[]) => number;\n };\n session: {\n recordInboundSession: (...args: unknown[]) => unknown;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n };\n config: {\n loadConfig: () => Promise<OpenClawConfig>;\n writeConfigFile?: (...args: unknown[]) => Promise<void>;\n };\n logging: { shouldLogVerbose(): boolean; getChildLogger(name: string): PluginLogger };\n state: { resolveStateDir(): string };\n}\n\nexport interface OpenClawConfig {\n channels?: Record<string, Record<string, unknown>>;\n plugins?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface OpenClawPluginServiceContext {\n config: OpenClawConfig;\n workspaceDir?: string;\n stateDir: string;\n logger: PluginLogger;\n}\n\nexport interface OpenClawPluginService {\n id: string;\n start: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;\n stop?: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;\n}\n\nexport interface OpenClawPluginToolContext {\n config?: OpenClawConfig;\n agentId?: string;\n sessionKey?: string;\n messageChannel?: string;\n [key: string]: unknown;\n}\n\nexport interface AgentTool {\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n execute: (params: Record<string, unknown>, ctx?: unknown) => Promise<unknown>;\n}\n\nexport type OpenClawPluginToolFactory = (ctx: OpenClawPluginToolContext) => AgentTool | AgentTool[] | null | undefined;\n\nexport interface OpenClawPluginApi {\n id: string;\n name: string;\n version?: string;\n description?: string;\n source: string;\n rootDir?: string;\n registrationMode: \"full\" | \"setup-only\" | \"setup-runtime\";\n config: OpenClawConfig;\n pluginConfig?: Record<string, unknown>;\n runtime: PluginRuntime;\n logger: PluginLogger;\n\n registerTool: (tool: AgentTool | OpenClawPluginToolFactory, opts?: { name?: string; names?: string[]; optional?: boolean }) => void;\n registerHook: (events: string | string[], handler: (...args: unknown[]) => void | Promise<void>, opts?: Record<string, unknown>) => void;\n registerHttpRoute: (params: Record<string, unknown>) => void;\n registerChannel: (registration: { plugin: ChannelPlugin } | ChannelPlugin) => void;\n registerGatewayMethod: (method: string, handler: (...args: unknown[]) => unknown) => void;\n registerService: (service: OpenClawPluginService) => void;\n registerCommand: (command: { name: string; description: string; handler: (...args: unknown[]) => void | Promise<void> }) => void;\n resolvePath: (input: string) => string;\n on: (hookName: string, handler: (...args: unknown[]) => void | Promise<void>, opts?: { priority?: number }) => void;\n}\n\nexport interface ChannelMeta {\n id: string;\n label: string;\n selectionLabel: string;\n docsPath?: string;\n blurb?: string;\n aliases?: string[];\n order?: number;\n}\n\nexport interface ChannelCapabilities {\n chatTypes: Array<\"direct\" | \"group\">;\n}\n\nexport interface ChannelConfigAdapter {\n listAccountIds: (cfg: OpenClawConfig) => string[];\n resolveAccount: (cfg: OpenClawConfig, accountId?: string) => Record<string, unknown>;\n}\n\nexport interface ChannelOutboundAdapter {\n deliveryMode: \"direct\" | \"queued\";\n sendText: (ctx: SendTextContext) => Promise<{ ok: boolean; error?: string }>;\n}\n\nexport interface SendTextContext {\n text: string;\n conversationId?: string;\n accountId?: string;\n replyTo?: string;\n [key: string]: unknown;\n}\n\nexport interface ChannelLifecycleAdapter {\n startAccount?: (accountId: string, config: Record<string, unknown>, logger: PluginLogger) => Promise<void>;\n stopAccount?: (accountId: string) => Promise<void>;\n}\n\nexport interface ChannelPlugin {\n id: string;\n meta: ChannelMeta;\n capabilities: ChannelCapabilities;\n config: ChannelConfigAdapter;\n outbound?: ChannelOutboundAdapter;\n lifecycle?: ChannelLifecycleAdapter;\n [key: string]: unknown;\n}\n\nexport interface DefinedPluginEntry {\n id: string;\n name: string;\n description: string;\n register: (api: OpenClawPluginApi) => void;\n}\n\nexport function definePluginEntry(opts: {\n id: string;\n name: string;\n description: string;\n register: (api: OpenClawPluginApi) => void;\n}): DefinedPluginEntry {\n return {\n id: opts.id,\n name: opts.name,\n description: opts.description,\n register: opts.register,\n };\n}\n\nexport function defineChannelPluginEntry<TPlugin extends ChannelPlugin>(opts: {\n id: string;\n name: string;\n description: string;\n plugin: TPlugin;\n setRuntime?: (runtime: PluginRuntime) => void;\n registerFull?: (api: OpenClawPluginApi) => void;\n}): DefinedPluginEntry {\n return definePluginEntry({\n id: opts.id,\n name: opts.name,\n description: opts.description,\n register(api) {\n api.registerChannel({ plugin: opts.plugin });\n if (opts.setRuntime) opts.setRuntime(api.runtime);\n if (api.registrationMode === \"full\" && opts.registerFull) {\n opts.registerFull(api);\n }\n },\n });\n}\n","export interface BounceMessage {\n type: \"message\" | \"accept\" | \"walk\" | \"propose_terms\" | \"counter_terms\" | \"research\";\n content: string;\n terms?: Record<string, any>;\n}\n\nconst SIMPLE_PREFIXES: Record<string, BounceMessage[\"type\"]> = {\n \"[ACCEPT]\": \"accept\",\n \"[WALK]\": \"walk\",\n \"[RESEARCH]\": \"research\",\n};\n\nconst TERMS_PREFIXES: Record<string, BounceMessage[\"type\"]> = {\n \"[TERMS]\": \"propose_terms\",\n \"[COUNTER]\": \"counter_terms\",\n};\n\nexport function parseResponse(text: string): BounceMessage {\n const trimmed = text.trim();\n\n for (const [prefix, type] of Object.entries(SIMPLE_PREFIXES)) {\n if (trimmed.startsWith(prefix)) {\n return { type, content: trimmed.slice(prefix.length).trim() };\n }\n }\n\n for (const [prefix, type] of Object.entries(TERMS_PREFIXES)) {\n if (trimmed.startsWith(prefix)) {\n const rest = trimmed.slice(prefix.length);\n const jsonEnd = rest.indexOf(\"}\");\n if (jsonEnd !== -1) {\n const jsonStr = rest.slice(0, jsonEnd + 1);\n try {\n const terms = JSON.parse(jsonStr);\n const content = rest.slice(jsonEnd + 1).trim();\n return { type, content, terms };\n } catch {\n return { type: \"message\", content: trimmed };\n }\n }\n return { type: \"message\", content: trimmed };\n }\n }\n\n return { type: \"message\", content: trimmed };\n}\n","import { parseResponse } from \"./connector-parser.js\";\nimport { NegotiationSession } from \"./connector-session.js\";\nimport type {\n ChannelPlugin,\n OpenClawConfig,\n PluginLogger,\n SendTextContext,\n} from \"./sdk-types.js\";\n\nconst activeSessions = new Map<string, NegotiationSession>();\n\nexport function getActiveSession(negotiationId: string): NegotiationSession | undefined {\n return activeSessions.get(negotiationId);\n}\n\nexport function setActiveSession(negotiationId: string, session: NegotiationSession): void {\n activeSessions.set(negotiationId, session);\n}\n\nexport function removeActiveSession(negotiationId: string): void {\n const session = activeSessions.get(negotiationId);\n if (session) {\n session.close();\n activeSessions.delete(negotiationId);\n }\n}\n\nexport function getActiveNegotiationId(): string | undefined {\n const entries = [...activeSessions.entries()];\n return entries.length > 0 ? entries[0]![0] : undefined;\n}\n\nexport function createBouncerChannel(logger: PluginLogger): ChannelPlugin {\n return {\n id: \"bouncer\",\n\n meta: {\n id: \"bouncer\",\n label: \"Bouncer Protocol\",\n selectionLabel: \"Bouncer Protocol (Agent Negotiation)\",\n docsPath: \"/channels/bouncer\",\n blurb: \"Real-time agent-to-agent negotiation via the Bouncer Protocol\",\n aliases: [\"bouncer-protocol\"],\n order: 90,\n },\n\n capabilities: {\n chatTypes: [\"direct\"],\n },\n\n config: {\n listAccountIds(cfg: OpenClawConfig): string[] {\n const bouncer = cfg.channels?.bouncer as Record<string, unknown> | undefined;\n if (!bouncer?.agentId) return [];\n return [bouncer.agentId as string];\n },\n\n resolveAccount(cfg: OpenClawConfig, accountId?: string): Record<string, unknown> {\n const bouncer = cfg.channels?.bouncer as Record<string, unknown> | undefined;\n return bouncer ?? { accountId };\n },\n },\n\n outbound: {\n deliveryMode: \"direct\",\n\n async sendText(ctx: SendTextContext): Promise<{ ok: boolean; error?: string }> {\n const negId = ctx.conversationId ?? getActiveNegotiationId();\n if (!negId) {\n return { ok: false, error: \"No active negotiation session\" };\n }\n\n const session = activeSessions.get(negId);\n if (!session) {\n return { ok: false, error: `No session for negotiation ${negId}` };\n }\n\n const parsed = parseResponse(ctx.text);\n\n session.sendThinking();\n\n await new Promise((r) => setTimeout(r, 200));\n\n session.send(parsed);\n logger.info(`[bouncer] Sent ${parsed.type}: ${parsed.content.slice(0, 80)}...`);\n\n return { ok: true };\n },\n },\n };\n}\n","import { EventEmitter } from \"events\";\nimport WebSocket from \"ws\";\n\nlet requestCounter = 0;\n\nexport interface LobbyClientOpts {\n apiUrl: string;\n token: string;\n agentId: string;\n reconnectBaseMs?: number;\n reconnectMaxMs?: number;\n}\n\nexport class LobbyClient extends EventEmitter {\n private ws: WebSocket | null = null;\n private opts: Required<LobbyClientOpts>;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private closed = false;\n private lastHeartbeatAt = 0;\n private watchdogTimer: ReturnType<typeof setInterval> | null = null;\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n\n private static readonly HEARTBEAT_STALE_MS = 45_000;\n private static readonly WATCHDOG_INTERVAL_MS = 15_000;\n private static readonly CLIENT_PING_INTERVAL_MS = 25_000;\n\n constructor(opts: LobbyClientOpts) {\n super();\n this.opts = {\n reconnectBaseMs: 1000,\n reconnectMaxMs: 30_000,\n ...opts,\n };\n }\n\n connect(): Promise<void> {\n this.closed = false;\n return this._connect();\n }\n\n private _connect(): Promise<void> {\n this.stopTimers();\n return new Promise((resolve, reject) => {\n const url = `${this.opts.apiUrl}/v1/agents/${this.opts.agentId}/ws?token=${this.opts.token}`;\n const ws = new WebSocket(url);\n this.ws = ws;\n\n ws.on(\"open\", () => {\n this.reconnectAttempt = 0;\n this.lastHeartbeatAt = Date.now();\n this.startWatchdog();\n this.startClientPing();\n });\n\n ws.on(\"message\", (raw) => {\n try {\n const data = JSON.parse(raw.toString());\n if (data.type === \"connected\") {\n this.lastHeartbeatAt = Date.now();\n this.emit(\"connected\", data);\n resolve();\n } else if (data.type === \"heartbeat\") {\n this.lastHeartbeatAt = Date.now();\n this.emit(\"heartbeat\", data);\n } else if (data.type === \"error\") {\n this.emit(\"error\", new Error(data.error));\n }\n this.emit(data.type, data);\n } catch {}\n });\n\n ws.on(\"close\", () => {\n this.stopTimers();\n if (!this.closed) {\n this.scheduleReconnect();\n }\n });\n\n ws.on(\"error\", (err) => {\n if (this.reconnectAttempt === 0 && ws.readyState === WebSocket.CONNECTING) {\n reject(err);\n }\n });\n });\n }\n\n private startWatchdog() {\n this.watchdogTimer = setInterval(() => {\n if (this.closed) return;\n const staleMs = Date.now() - this.lastHeartbeatAt;\n if (staleMs > LobbyClient.HEARTBEAT_STALE_MS) {\n this.emit(\"stale\", { staleMs });\n this.forceReconnect();\n }\n }, LobbyClient.WATCHDOG_INTERVAL_MS);\n }\n\n private startClientPing() {\n this.pingTimer = setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n try {\n this.ws.ping();\n } catch {}\n }\n }, LobbyClient.CLIENT_PING_INTERVAL_MS);\n }\n\n private stopTimers() {\n if (this.watchdogTimer) { clearInterval(this.watchdogTimer); this.watchdogTimer = null; }\n if (this.pingTimer) { clearInterval(this.pingTimer); this.pingTimer = null; }\n }\n\n private forceReconnect() {\n this.stopTimers();\n if (this.ws) {\n try { this.ws.terminate(); } catch {}\n this.ws = null;\n }\n if (!this.closed) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect() {\n if (this.closed) return;\n const delay = Math.min(\n this.opts.reconnectBaseMs * Math.pow(2, this.reconnectAttempt),\n this.opts.reconnectMaxMs\n );\n this.reconnectAttempt++;\n this.reconnectTimer = setTimeout(() => {\n if (!this.closed) {\n this._connect().catch(() => {});\n }\n }, delay);\n }\n\n accept(negotiationId: string): void {\n this.send({ type: \"accept_negotiation\", negotiation_id: negotiationId });\n }\n\n decline(negotiationId: string, reason?: string): void {\n this.send({ type: \"decline_negotiation\", negotiation_id: negotiationId, reason });\n }\n\n isConnected(): boolean {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;\n if (this.lastHeartbeatAt > 0) {\n const staleMs = Date.now() - this.lastHeartbeatAt;\n if (staleMs > LobbyClient.HEARTBEAT_STALE_MS) return false;\n }\n return true;\n }\n\n send(data: any): boolean {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(data));\n return true;\n }\n return false;\n }\n\n request(msg: Record<string, unknown>, responseType: string, timeoutMs = 30_000): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected()) {\n const staleMs = this.lastHeartbeatAt > 0 ? Date.now() - this.lastHeartbeatAt : -1;\n reject(new Error(`Lobby WS not connected (readyState: ${this.ws?.readyState ?? \"null\"}, lastHeartbeat: ${staleMs}ms ago) — cannot send ${msg.type}`));\n return;\n }\n\n const requestId = `req_${++requestCounter}_${Date.now()}`;\n console.log(`[lobby-request] Sending ${msg.type} with request_id=${requestId}, waiting for ${responseType}`);\n\n const timer = setTimeout(() => {\n const staleMs = this.lastHeartbeatAt > 0 ? Date.now() - this.lastHeartbeatAt : -1;\n console.log(`[lobby-request] TIMEOUT for ${requestId}: readyState=${this.ws?.readyState}, lastHeartbeat=${staleMs}ms ago, listenerCount(${responseType})=${this.listenerCount(responseType)}`);\n cleanup();\n reject(new Error(`WS request timed out waiting for ${responseType} (sent ${msg.type}, waited ${timeoutMs}ms, lastHeartbeat: ${staleMs}ms ago)`));\n }, timeoutMs);\n\n const handler = (data: any) => {\n console.log(`[lobby-request] Got ${responseType} event: request_id=${data.request_id} (waiting for ${requestId})`);\n if (data.request_id === requestId) {\n cleanup();\n if (data.error) {\n reject(new Error(data.error));\n } else {\n resolve(data);\n }\n }\n };\n\n const cleanup = () => {\n clearTimeout(timer);\n this.removeListener(responseType, handler);\n };\n\n this.on(responseType, handler);\n const sent = this.send({ ...msg, request_id: requestId });\n if (!sent) {\n cleanup();\n reject(new Error(`Failed to send ${msg.type} — WS connection dropped between check and send`));\n } else {\n console.log(`[lobby-request] Message sent successfully, readyState=${this.ws?.readyState}`);\n }\n });\n }\n\n close(): void {\n this.closed = true;\n this.stopTimers();\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer);\n if (this.ws) {\n try { this.ws.close(); } catch {}\n this.ws = null;\n }\n }\n}\n","import { EventEmitter } from \"events\";\nimport WebSocket from \"ws\";\n\nexport interface NegotiationSessionOpts {\n apiUrl: string;\n token: string;\n negotiationId: string;\n agentId: string;\n}\n\nexport class NegotiationSession extends EventEmitter {\n private ws: WebSocket | null = null;\n private opts: NegotiationSessionOpts;\n private seenMessageIds = new Set<string>();\n private myAgentId: string;\n\n constructor(opts: NegotiationSessionOpts) {\n super();\n this.opts = opts;\n this.myAgentId = opts.agentId;\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const url = `${this.opts.apiUrl}/v1/negotiations/${this.opts.negotiationId}/ws?token=${this.opts.token}`;\n const ws = new WebSocket(url);\n this.ws = ws;\n\n ws.on(\"message\", (raw) => {\n try {\n const data = JSON.parse(raw.toString());\n\n if (data.type === \"connected\") {\n if (data.agent_id) this.myAgentId = data.agent_id;\n this.emit(\"connected\", data);\n resolve();\n } else if (data.type === \"negotiation_message\") {\n const msg = data.message ?? {\n id: data.id,\n from_agent_id: data.from_agent_id,\n type: data.message_type ?? data.type,\n content: data.content,\n terms: data.terms,\n is_catchup: data.is_catchup,\n created_at: data.created_at,\n };\n\n const msgId = msg.id;\n if (msgId && this.seenMessageIds.has(msgId)) return;\n if (msgId) this.seenMessageIds.add(msgId);\n\n if (msg.from_agent_id === this.myAgentId) return;\n\n this.emit(\"incoming_message\", msg);\n } else if (data.type === \"negotiation_started\") {\n this.emit(\"negotiation_started\", data);\n } else if (data.type === \"negotiation_ended\") {\n this.emit(\"ended\", data);\n this.close();\n } else if (data.type === \"message_ack\") {\n if (data.message?.id) this.seenMessageIds.add(data.message.id);\n this.emit(\"message_ack\", data);\n } else if (data.type === \"agent_thinking\") {\n this.emit(\"agent_thinking\", data);\n } else if (data.type === \"error\") {\n this.emit(\"error\", new Error(data.error));\n }\n } catch {}\n });\n\n ws.on(\"error\", (err) => {\n if (ws.readyState === WebSocket.CONNECTING) {\n reject(err);\n }\n });\n\n ws.on(\"close\", () => {\n this.emit(\"disconnected\");\n });\n });\n }\n\n send(msg: { type: string; content?: string; terms?: object }): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n sendThinking(): void {\n this.send({ type: \"thinking\" });\n }\n\n close(): void {\n if (this.ws) {\n try { this.ws.close(); } catch {}\n this.ws = null;\n }\n }\n}\n","import { LobbyClient } from \"./connector-lobby.js\";\nimport { NegotiationSession } from \"./connector-session.js\";\nimport { parseResponse } from \"./connector-parser.js\";\nimport {\n setActiveSession,\n removeActiveSession,\n} from \"./bouncer-channel.js\";\nimport type { BouncerPluginConfig, NegotiationState } from \"./types.js\";\nimport type {\n OpenClawPluginService,\n OpenClawPluginServiceContext,\n PluginLogger,\n PluginRuntime,\n} from \"./sdk-types.js\";\n\nlet lobbyClient: LobbyClient | null = null;\n\nexport function getLobbyClient(): LobbyClient | null {\n return lobbyClient;\n}\nlet activeNegotiation: NegotiationState | null = null;\nlet pluginRuntime: PluginRuntime | null = null;\n\nfunction resolveAgentFromBindings(cfg: any, channel: string): string | null {\n const bindings = cfg?.bindings;\n if (!Array.isArray(bindings)) return null;\n for (const b of bindings) {\n if (b?.match?.channel === channel && b?.agentId) {\n return b.agentId;\n }\n }\n return null;\n}\n\nlet serviceStarted = false;\n\nexport function setRuntime(rt: PluginRuntime): void {\n pluginRuntime = rt;\n}\n\nexport async function ensureServiceStarted(log: PluginLogger): Promise<void> {\n if (serviceStarted || lobbyClient) return;\n if (!pluginRuntime) return;\n\n try {\n const cfg = await pluginRuntime.config.loadConfig();\n const bouncerCfg = cfg?.channels?.bouncer as Record<string, unknown> | undefined;\n if (!bouncerCfg?.role) return;\n\n const config: BouncerPluginConfig = {\n role: bouncerCfg.role as \"bouncer\" | \"brand\",\n apiUrl: bouncerCfg.apiUrl as string,\n apiKey: bouncerCfg.apiKey as string,\n agentId: bouncerCfg.agentId as string,\n autoAccept: (bouncerCfg.autoAccept as boolean) ?? true,\n llmTimeoutMs: (bouncerCfg.llmTimeoutMs as number) ?? 25_000,\n };\n\n serviceStarted = true;\n log.info(`[bouncer] Self-starting service — role: ${config.role}, agent: ${config.agentId}`);\n\n await startLobby(config, log);\n } catch (err: any) {\n log.error(`[bouncer] Self-start failed: ${err.message}`);\n serviceStarted = false;\n }\n}\n\nexport function getActiveNegotiation(): NegotiationState | null {\n return activeNegotiation;\n}\n\nexport function createBouncerService(config: BouncerPluginConfig): OpenClawPluginService {\n return {\n id: \"bouncer-negotiation-service\",\n\n async start(ctx: OpenClawPluginServiceContext) {\n const log = ctx.logger;\n\n await startLobby(config, log);\n },\n\n async stop() {\n if (lobbyClient) {\n lobbyClient.close();\n lobbyClient = null;\n }\n if (activeNegotiation) {\n removeActiveSession(activeNegotiation.negotiationId);\n activeNegotiation = null;\n }\n },\n };\n}\n\nasync function startLobby(config: BouncerPluginConfig, log: PluginLogger): Promise<void> {\n const wsBase = config.apiUrl.replace(/^http/, \"ws\");\n\n lobbyClient = new LobbyClient({\n apiUrl: wsBase,\n token: config.apiKey,\n agentId: config.agentId,\n reconnectBaseMs: 1_000,\n reconnectMaxMs: 30_000,\n });\n\n lobbyClient.on(\"connected\", () => {\n log.info(`[bouncer] Lobby connected (${config.role} mode).`);\n });\n\n if (config.role === \"bouncer\") {\n lobbyClient.on(\"negotiation_requested\", (data: any) => {\n handleNegotiationRequested(data, config, wsBase, log);\n });\n }\n\n lobbyClient.on(\"heartbeat\", () => {\n log.debug(\"[bouncer] Lobby heartbeat\");\n });\n\n lobbyClient.on(\"stale\", (data: any) => {\n log.warn(`[bouncer] Lobby connection stale (${data.staleMs}ms since last heartbeat) — forcing reconnect`);\n });\n\n try {\n await lobbyClient.connect();\n } catch (err: any) {\n log.error(`[bouncer] Lobby connection failed: ${err.message}`);\n throw err;\n }\n}\n\nasync function handleNegotiationRequested(\n data: any,\n config: BouncerPluginConfig,\n wsBase: string,\n log: PluginLogger,\n): Promise<void> {\n const negId = data.negotiation_id;\n\n if (activeNegotiation) {\n log.info(`[bouncer] Declining ${negId} — already in negotiation ${activeNegotiation.negotiationId}`);\n lobbyClient?.decline(negId, \"busy — already in a negotiation\");\n return;\n }\n\n if (!config.autoAccept) {\n log.info(`[bouncer] Negotiation ${negId} requested but autoAccept is off. Declining.`);\n lobbyClient?.decline(negId, \"auto-accept disabled\");\n return;\n }\n\n log.info(`[bouncer] Accepting negotiation ${negId}`);\n lobbyClient?.accept(negId);\n\n activeNegotiation = {\n negotiationId: negId,\n status: \"pending\",\n otherAgentId: data.brand?.id,\n offerContext: data.offer\n ? { product: data.offer.product, terms: data.offer.terms, opening_message: data.offer.opening_message }\n : undefined,\n };\n\n await connectToNegotiationRoom(negId, config, wsBase, log);\n}\n\nexport async function connectToNegotiationRoom(\n negotiationId: string,\n config: BouncerPluginConfig,\n wsBase: string,\n log: PluginLogger,\n): Promise<void> {\n const session = new NegotiationSession({\n apiUrl: wsBase,\n token: config.apiKey,\n negotiationId,\n agentId: config.agentId,\n });\n\n session.on(\"connected\", () => {\n log.info(`[bouncer] Connected to negotiation room ${negotiationId}`);\n });\n\n session.on(\"negotiation_started\", (data: any) => {\n log.info(`[bouncer] Negotiation ${negotiationId} started`);\n if (activeNegotiation) {\n activeNegotiation.status = \"live\";\n if (data.queue_context) {\n (activeNegotiation as any).queueContext = data.queue_context;\n }\n if (data.relationship) {\n (activeNegotiation as any).relationship = data.relationship;\n }\n }\n });\n\n let dispatching = false;\n session.on(\"incoming_message\", (msg: any) => {\n if (dispatching) {\n log.debug(`[bouncer] Skipping message while dispatch in progress`);\n return;\n }\n log.info(`[bouncer] Message from ${msg.from_agent_id}: ${(msg.content ?? \"\").slice(0, 80)}...`);\n dispatching = true;\n dispatchToAgent(negotiationId, msg, config, session, log).finally(() => {\n dispatching = false;\n });\n });\n\n session.on(\"agent_thinking\", () => {\n log.debug(`[bouncer] Other agent thinking in ${negotiationId}`);\n });\n\n session.on(\"ended\", (data: any) => {\n log.info(`[bouncer] Negotiation ${negotiationId} ended: ${data?.status ?? \"unknown\"}`);\n removeActiveSession(negotiationId);\n activeNegotiation = null;\n });\n\n session.on(\"disconnected\", () => {\n log.warn(`[bouncer] Disconnected from negotiation ${negotiationId}`);\n });\n\n setActiveSession(negotiationId, session);\n\n try {\n await session.connect();\n } catch (err: any) {\n log.error(`[bouncer] Failed to connect to negotiation ${negotiationId}: ${err.message}`);\n removeActiveSession(negotiationId);\n activeNegotiation = null;\n }\n}\n\nasync function dispatchToAgent(\n negotiationId: string,\n msg: any,\n config: BouncerPluginConfig,\n session: NegotiationSession,\n log: PluginLogger,\n): Promise<void> {\n if (!pluginRuntime) {\n log.error(\"[bouncer] Runtime not set — cannot dispatch inbound message to agent\");\n return;\n }\n\n const rt = pluginRuntime;\n\n try {\n const currentCfg = await rt.config.loadConfig();\n\n const resolvedAgent = resolveAgentFromBindings(currentCfg, \"bouncer\");\n if (resolvedAgent) {\n log.info(`[bouncer] Routing negotiation ${negotiationId} to agent: ${resolvedAgent}`);\n }\n\n const msgCtx = rt.channel.reply.finalizeInboundContext({\n Body: msg.content ?? \"\",\n RawBody: msg.content ?? \"\",\n CommandBody: msg.content ?? \"\",\n From: `bouncer:${msg.from_agent_id}`,\n To: `bouncer:${config.agentId}`,\n SessionKey: `bouncer:${negotiationId}`,\n AccountId: config.agentId,\n OriginatingChannel: \"bouncer\",\n OriginatingTo: `bouncer:${msg.from_agent_id}`,\n ChatType: \"direct\",\n SenderName: msg.from_agent_id,\n SenderId: msg.from_agent_id,\n Provider: \"bouncer\",\n Surface: \"bouncer\",\n ConversationLabel: `Negotiation ${negotiationId}`,\n Timestamp: Date.now(),\n CommandAuthorized: true,\n ...(resolvedAgent ? { AgentId: resolvedAgent, TargetAgentId: resolvedAgent, ResolvedAgentId: resolvedAgent } : {}),\n });\n\n await rt.channel.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: msgCtx,\n cfg: currentCfg,\n dispatcherOptions: {\n deliver: async (payload) => {\n const text = payload?.text ?? payload?.body;\n if (!text) return;\n\n const parsed = parseResponse(text);\n session.sendThinking();\n await new Promise((r) => setTimeout(r, 200));\n session.send(parsed);\n log.info(`[bouncer] Agent replied (${parsed.type}): ${parsed.content.slice(0, 80)}...`);\n },\n onReplyStart: () => {\n session.sendThinking();\n },\n },\n });\n } catch (err: any) {\n log.error(`[bouncer] Dispatch failed for negotiation ${negotiationId}: ${err.message}`);\n }\n}\n","export interface BouncerPluginConfig {\n role: \"bouncer\" | \"brand\";\n apiUrl: string;\n apiKey: string;\n agentId: string;\n autoAccept?: boolean;\n llmTimeoutMs?: number;\n}\n\nexport interface NegotiationState {\n negotiationId: string;\n status: \"pending\" | \"live\" | \"ended\";\n otherAgentId?: string;\n offerContext?: {\n product: string;\n terms: string;\n opening_message: string;\n };\n}\n\nexport interface InboundNegotiationMessage {\n negotiationId: string;\n fromAgentId: string;\n type: string;\n content: string;\n terms?: Record<string, unknown>;\n timestamp: string;\n}\n\nexport function resolveConfig(pluginConfig: Record<string, unknown> | undefined): BouncerPluginConfig {\n if (!pluginConfig) throw new Error(\"Bouncer plugin config is required\");\n\n const role = pluginConfig.role as string;\n if (role !== \"bouncer\" && role !== \"brand\") {\n throw new Error(`Invalid role \"${role}\" — must be \"bouncer\" or \"brand\"`);\n }\n\n return {\n role,\n apiUrl: pluginConfig.apiUrl as string,\n apiKey: pluginConfig.apiKey as string,\n agentId: pluginConfig.agentId as string,\n autoAccept: (pluginConfig.autoAccept as boolean) ?? true,\n llmTimeoutMs: (pluginConfig.llmTimeoutMs as number) ?? 25_000,\n };\n}\n\nexport function wsUrl(apiUrl: string): string {\n return apiUrl.replace(/^http/, \"ws\");\n}\n","import type { AgentTool, PluginLogger } from \"./sdk-types.js\";\nimport type { BouncerPluginConfig } from \"./types.js\";\nimport { connectToNegotiationRoom, getLobbyClient } from \"./service.js\";\nimport { wsUrl } from \"./types.js\";\n\nexport function createBrandTools(config: BouncerPluginConfig, logger: PluginLogger): AgentTool[] {\n if (config.role !== \"brand\") return [];\n\n const bouncerBrowse: AgentTool = {\n name: \"bouncer_browse\",\n description:\n \"Browse available Bouncer agents in the directory. Returns a list of bouncers \" +\n \"with their name, listing, tags, and reputation score. Use this to find a \" +\n \"bouncer to target with an offer.\",\n parameters: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n description: \"Max results to return (default: 20)\",\n },\n },\n },\n\n async execute(params: Record<string, unknown>): Promise<unknown> {\n const lobby = getLobbyClient();\n if (!lobby) return { error: \"Not connected to lobby\" };\n\n try {\n const result = await lobby.request(\n { type: \"browse_bouncers\", limit: params.limit ?? 20 },\n \"browse_bouncers_result\",\n );\n logger.info(`[bouncer] Browse returned ${result.bouncers?.length ?? 0} bouncers`);\n return result.bouncers;\n } catch (err: any) {\n return { error: `Browse failed: ${err.message}` };\n }\n },\n };\n\n const bouncerProfile: AgentTool = {\n name: \"bouncer_profile\",\n description:\n \"Get the full profile of a specific Bouncer agent, including their listing, \" +\n \"enrichment data, engagement rules, and verified credentials. Use this before \" +\n \"crafting a personalized offer.\",\n parameters: {\n type: \"object\",\n properties: {\n bouncer_id: {\n type: \"string\",\n description: \"The Bouncer agent's UUID\",\n },\n },\n required: [\"bouncer_id\"],\n },\n\n async execute(params: Record<string, unknown>): Promise<unknown> {\n const lobby = getLobbyClient();\n if (!lobby) return { error: \"Not connected to lobby\" };\n\n try {\n const result = await lobby.request(\n { type: \"get_profile\", bouncer_id: params.bouncer_id },\n \"get_profile_result\",\n );\n if (result.error) return { error: result.error };\n return result.profile;\n } catch (err: any) {\n return { error: `Profile fetch failed: ${err.message}` };\n }\n },\n };\n\n const bouncerOffer: AgentTool = {\n name: \"bouncer_offer\",\n description:\n \"Submit an offer to a Bouncer agent and create a negotiation. This sends your \" +\n \"offer and automatically connects you to the negotiation room when the bouncer \" +\n \"accepts. Returns the offer_id and negotiation_id.\",\n parameters: {\n type: \"object\",\n properties: {\n bouncer_id: {\n type: \"string\",\n description: \"The target Bouncer's UUID\",\n },\n product: {\n type: \"string\",\n description: \"Product or service being offered\",\n },\n terms: {\n type: \"string\",\n description: \"Deal terms (e.g. '$20 credit + free delivery')\",\n },\n opening_message: {\n type: \"string\",\n description: \"Personalized opening message to the Bouncer\",\n },\n priority_bid: {\n type: \"number\",\n description: \"Priority bid in USDC (e.g. 2.0)\",\n },\n arena: {\n type: \"boolean\",\n description: \"Practice mode — no real USDC (default: false)\",\n },\n },\n required: [\"bouncer_id\", \"product\", \"terms\", \"opening_message\", \"priority_bid\"],\n },\n\n async execute(params: Record<string, unknown>): Promise<unknown> {\n const lobby = getLobbyClient();\n if (!lobby) {\n logger.error(\"[bouncer] bouncer_offer: getLobbyClient() returned null — lobby not initialized\");\n return { error: \"Not connected to lobby\" };\n }\n\n const connected = lobby.isConnected();\n logger.info(`[bouncer] bouncer_offer: lobby.isConnected() = ${connected}`);\n if (!connected) {\n logger.error(\"[bouncer] bouncer_offer: lobby exists but isConnected() is false — WS may be reconnecting\");\n return { error: \"Lobby WS not connected — may be reconnecting. Try again in a few seconds.\" };\n }\n\n const bouncerId = params.bouncer_id as string;\n\n try {\n logger.info(`[bouncer] Submitting offer to ${bouncerId}`);\n const sendStart = Date.now();\n\n const offerResult = await lobby.request(\n {\n type: \"submit_offer\",\n bouncer_id: bouncerId,\n product: params.product,\n terms: params.terms,\n opening_message: params.opening_message,\n priority_bid: params.priority_bid,\n arena: params.arena ?? false,\n },\n \"submit_offer_result\",\n );\n\n logger.info(`[bouncer] submit_offer response in ${Date.now() - sendStart}ms`);\n\n if (offerResult.error) {\n return { error: `Offer submission failed: ${offerResult.error}` };\n }\n\n const offerId = offerResult.offer_id;\n logger.info(`[bouncer] Offer submitted: ${offerId}`);\n\n logger.info(`[bouncer] Creating negotiation for offer ${offerId}`);\n const negResult = await lobby.request(\n { type: \"create_negotiation\", offer_id: offerId, bouncer_id: bouncerId },\n \"create_negotiation_result\",\n );\n\n if (negResult.error) {\n return { error: `Negotiation creation failed: ${negResult.error}`, offer_id: offerId };\n }\n\n const negotiationId = negResult.negotiation_id;\n logger.info(`[bouncer] Negotiation created: ${negotiationId}`);\n\n logger.info(`[bouncer] Waiting for bouncer to accept (via WS)...`);\n const accepted = await waitForAcceptanceWS(negotiationId, 120_000);\n\n if (!accepted) {\n return { status: \"declined_or_timeout\", offer_id: offerId, negotiation_id: negotiationId };\n }\n\n logger.info(`[bouncer] Accepted! Connecting to negotiation room...`);\n await connectToNegotiationRoom(negotiationId, config, wsUrl(config.apiUrl), logger);\n\n return {\n status: \"connected\",\n offer_id: offerId,\n negotiation_id: negotiationId,\n message: \"Connected to negotiation room. Incoming messages will appear as chat messages.\",\n };\n } catch (err: any) {\n return { error: `Offer flow failed: ${err.message}` };\n }\n },\n };\n\n return [bouncerBrowse, bouncerProfile, bouncerOffer];\n}\n\nfunction waitForAcceptanceWS(negotiationId: string, timeoutMs: number): Promise<boolean> {\n return new Promise((resolve) => {\n const lobby = getLobbyClient();\n if (!lobby) {\n resolve(false);\n return;\n }\n\n const timer = setTimeout(() => {\n cleanup();\n resolve(false);\n }, timeoutMs);\n\n const onAccepted = (data: any) => {\n if (data.negotiation_id === negotiationId) {\n cleanup();\n resolve(true);\n }\n };\n\n const onDeclined = (data: any) => {\n if (data.negotiation_id === negotiationId) {\n cleanup();\n resolve(false);\n }\n };\n\n const cleanup = () => {\n clearTimeout(timer);\n lobby.removeListener(\"negotiation_accepted\", onAccepted);\n lobby.removeListener(\"negotiation_declined\", onDeclined);\n };\n\n lobby.on(\"negotiation_accepted\", onAccepted);\n lobby.on(\"negotiation_declined\", onDeclined);\n });\n}\n","import { definePluginEntry } from \"./src/sdk-types.js\";\nimport { createBouncerChannel } from \"./src/bouncer-channel.js\";\nimport { createBouncerService, setRuntime, ensureServiceStarted } from \"./src/service.js\";\nimport { createBrandTools } from \"./src/tools.js\";\nimport { resolveConfig } from \"./src/types.js\";\nimport type { OpenClawPluginApi, PluginLogger } from \"./src/sdk-types.js\";\n\nlet pluginLogger: PluginLogger = {\n info: console.log,\n warn: console.warn,\n error: console.error,\n debug: () => {},\n};\n\nconst channel = createBouncerChannel(pluginLogger);\n\nexport default definePluginEntry({\n id: \"bouncer\",\n name: \"Bouncer Protocol\",\n description: \"Agent-to-agent negotiation channel via the Bouncer Protocol. \" +\n \"Handles WebSocket lifecycle, heartbeats, echo filtering, and protocol \" +\n \"message formatting so the LLM only deals with plain text.\",\n\n register(api: OpenClawPluginApi) {\n const logger = api.logger ?? pluginLogger;\n pluginLogger = logger;\n\n api.registerChannel({ plugin: channel });\n setRuntime(api.runtime);\n\n if (api.runtime.logging) {\n const child = api.runtime.logging.getChildLogger(\"bouncer\");\n if (child) pluginLogger = child;\n }\n\n const bouncerConfig = resolveChannelConfig(api);\n if (!bouncerConfig) {\n logger.warn(\"[bouncer] No bouncer channel config found — will self-start from runtime config.\");\n setTimeout(() => {\n ensureServiceStartedWithTools(api, pluginLogger).catch((err: any) => {\n pluginLogger.error(`[bouncer] Deferred start failed: ${err.message}`);\n });\n }, 2_000);\n return;\n }\n\n const config = resolveConfig(bouncerConfig);\n logger.info(`[bouncer] Registering plugin — role: ${config.role}, agent: ${config.agentId}`);\n\n api.registerService(createBouncerService(config));\n\n const tools = createBrandTools(config, logger);\n for (const tool of tools) {\n api.registerTool(tool, { name: tool.name });\n }\n\n logger.info(`[bouncer] Plugin registered. Role: ${config.role}`);\n if (config.role === \"bouncer\") {\n logger.info(\"[bouncer] Lobby service will start on gateway boot.\");\n } else {\n logger.info(\"[bouncer] Brand tools registered: bouncer_browse, bouncer_profile, bouncer_offer\");\n }\n },\n});\n\nasync function ensureServiceStartedWithTools(api: OpenClawPluginApi, log: PluginLogger): Promise<void> {\n try {\n const cfg = await api.runtime.config.loadConfig();\n const bouncerCfg = cfg?.channels?.bouncer as Record<string, unknown> | undefined;\n if (!bouncerCfg?.role) {\n log.warn(\"[bouncer] Deferred start: no channels.bouncer.role found in runtime config.\");\n return;\n }\n\n const config = resolveConfig(bouncerCfg);\n log.info(`[bouncer] Deferred registration — role: ${config.role}, agent: ${config.agentId}`);\n\n api.registerService(createBouncerService(config));\n\n const tools = createBrandTools(config, log);\n for (const tool of tools) {\n api.registerTool(tool, { name: tool.name });\n }\n\n if (config.role === \"bouncer\") {\n log.info(\"[bouncer] Lobby service registered via deferred start.\");\n } else {\n log.info(\"[bouncer] Brand tools registered via deferred start: bouncer_browse, bouncer_profile, bouncer_offer\");\n }\n\n await ensureServiceStarted(log);\n } catch (err: any) {\n log.error(`[bouncer] Deferred start failed: ${err.message}`);\n }\n}\n\nfunction resolveChannelConfig(api: OpenClawPluginApi): Record<string, unknown> | null {\n const fromChannels = api.config?.channels?.bouncer as Record<string, unknown> | undefined;\n if (fromChannels && fromChannels.role) return fromChannels;\n\n if (api.pluginConfig && Object.keys(api.pluginConfig).length > 0) {\n return api.pluginConfig;\n }\n\n if (fromChannels && !fromChannels.role) {\n pluginLogger.warn(\n \"[bouncer] channels.bouncer exists but has no 'role' — check config. \" +\n \"Required: role, apiUrl, apiKey, agentId\"\n );\n }\n\n return null;\n}\n"],"mappings":"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","names":["EventEmitter","WebSocket","channel"]}
|
|
1
|
+
{"version":3,"sources":["../src/sdk-types.ts","../src/connector-parser.ts","../src/bouncer-channel.ts","../src/connector-lobby.ts","../src/connector-session.ts","../src/service.ts","../src/types.ts","../src/tools.ts","../index.ts"],"sourcesContent":["/**\n * Minimal type stubs for the OpenClaw Plugin SDK.\n *\n * When installed into an OpenClaw environment, replace these with:\n * import { definePluginEntry } from \"openclaw/plugin-sdk/core\";\n *\n * These stubs match the contract from openclaw/openclaw src/plugin-sdk/core.ts\n * and src/plugins/types.ts as of 2026-03.\n */\n\nexport interface PluginLogger {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n debug(msg: string, ...args: unknown[]): void;\n}\n\nexport interface ReplyPayload {\n text?: string;\n body?: string;\n mediaUrl?: string;\n mediaUrls?: string[];\n [key: string]: unknown;\n}\n\nexport interface MsgContext {\n Body?: string;\n BodyForAgent?: string;\n RawBody?: string;\n CommandBody?: string;\n From?: string;\n To?: string;\n SessionKey?: string;\n AccountId?: string;\n OriginatingChannel?: string;\n OriginatingTo?: string;\n ChatType?: string;\n SenderName?: string;\n SenderId?: string;\n Provider?: string;\n Surface?: string;\n ConversationLabel?: string;\n Timestamp?: number;\n CommandAuthorized?: boolean;\n [key: string]: unknown;\n}\n\nexport type FinalizedMsgContext = Omit<MsgContext, \"CommandAuthorized\"> & {\n CommandAuthorized: boolean;\n};\n\nexport interface ReplyDispatcherWithTypingOptions {\n deliver: (payload: ReplyPayload, info: { kind: string }) => Promise<void>;\n onReplyStart?: () => Promise<void> | void;\n onIdle?: () => void;\n onCleanup?: () => void;\n [key: string]: unknown;\n}\n\nexport interface DispatchInboundResult {\n [key: string]: unknown;\n}\n\nexport interface PluginRuntime {\n channel: {\n reply: {\n finalizeInboundContext: <T extends Record<string, unknown>>(ctx: T) => T & FinalizedMsgContext;\n dispatchReplyWithBufferedBlockDispatcher: (params: {\n ctx: MsgContext | FinalizedMsgContext;\n cfg: OpenClawConfig;\n dispatcherOptions: ReplyDispatcherWithTypingOptions;\n replyOptions?: Record<string, unknown>;\n }) => Promise<DispatchInboundResult>;\n dispatchReplyFromConfig?: (...args: unknown[]) => Promise<unknown>;\n };\n debounce: {\n createInboundDebouncer: (...args: unknown[]) => unknown;\n resolveInboundDebounceMs: (...args: unknown[]) => number;\n };\n session: {\n recordInboundSession: (...args: unknown[]) => unknown;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n };\n config: {\n loadConfig: () => Promise<OpenClawConfig>;\n writeConfigFile?: (...args: unknown[]) => Promise<void>;\n };\n logging: { shouldLogVerbose(): boolean; getChildLogger(name: string): PluginLogger };\n state: { resolveStateDir(): string };\n}\n\nexport interface OpenClawConfig {\n channels?: Record<string, Record<string, unknown>>;\n plugins?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface OpenClawPluginServiceContext {\n config: OpenClawConfig;\n workspaceDir?: string;\n stateDir: string;\n logger: PluginLogger;\n}\n\nexport interface OpenClawPluginService {\n id: string;\n start: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;\n stop?: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;\n}\n\nexport interface OpenClawPluginToolContext {\n config?: OpenClawConfig;\n agentId?: string;\n sessionKey?: string;\n messageChannel?: string;\n [key: string]: unknown;\n}\n\nexport interface AgentTool {\n name: string;\n label?: string;\n description: string;\n parameters?: Record<string, unknown>;\n execute: (toolCallId: string, params: Record<string, unknown>, signal?: AbortSignal, onUpdate?: unknown) => Promise<unknown>;\n}\n\nexport type OpenClawPluginToolFactory = (ctx: OpenClawPluginToolContext) => AgentTool | AgentTool[] | null | undefined;\n\nexport interface OpenClawPluginApi {\n id: string;\n name: string;\n version?: string;\n description?: string;\n source: string;\n rootDir?: string;\n registrationMode: \"full\" | \"setup-only\" | \"setup-runtime\";\n config: OpenClawConfig;\n pluginConfig?: Record<string, unknown>;\n runtime: PluginRuntime;\n logger: PluginLogger;\n\n registerTool: (tool: AgentTool | OpenClawPluginToolFactory, opts?: { name?: string; names?: string[]; optional?: boolean }) => void;\n registerHook: (events: string | string[], handler: (...args: unknown[]) => void | Promise<void>, opts?: Record<string, unknown>) => void;\n registerHttpRoute: (params: Record<string, unknown>) => void;\n registerChannel: (registration: { plugin: ChannelPlugin } | ChannelPlugin) => void;\n registerGatewayMethod: (method: string, handler: (...args: unknown[]) => unknown) => void;\n registerService: (service: OpenClawPluginService) => void;\n registerCommand: (command: { name: string; description: string; handler: (...args: unknown[]) => void | Promise<void> }) => void;\n resolvePath: (input: string) => string;\n on: (hookName: string, handler: (...args: unknown[]) => void | Promise<void>, opts?: { priority?: number }) => void;\n}\n\nexport interface ChannelMeta {\n id: string;\n label: string;\n selectionLabel: string;\n docsPath?: string;\n blurb?: string;\n aliases?: string[];\n order?: number;\n}\n\nexport interface ChannelCapabilities {\n chatTypes: Array<\"direct\" | \"group\">;\n}\n\nexport interface ChannelConfigAdapter {\n listAccountIds: (cfg: OpenClawConfig) => string[];\n resolveAccount: (cfg: OpenClawConfig, accountId?: string) => Record<string, unknown>;\n}\n\nexport interface ChannelOutboundAdapter {\n deliveryMode: \"direct\" | \"queued\";\n sendText: (ctx: SendTextContext) => Promise<{ ok: boolean; error?: string }>;\n}\n\nexport interface SendTextContext {\n text: string;\n conversationId?: string;\n accountId?: string;\n replyTo?: string;\n [key: string]: unknown;\n}\n\nexport interface ChannelLifecycleAdapter {\n startAccount?: (accountId: string, config: Record<string, unknown>, logger: PluginLogger) => Promise<void>;\n stopAccount?: (accountId: string) => Promise<void>;\n}\n\nexport interface ChannelPlugin {\n id: string;\n meta: ChannelMeta;\n capabilities: ChannelCapabilities;\n config: ChannelConfigAdapter;\n outbound?: ChannelOutboundAdapter;\n lifecycle?: ChannelLifecycleAdapter;\n [key: string]: unknown;\n}\n\nexport interface DefinedPluginEntry {\n id: string;\n name: string;\n description: string;\n register: (api: OpenClawPluginApi) => void;\n}\n\nexport function definePluginEntry(opts: {\n id: string;\n name: string;\n description: string;\n register: (api: OpenClawPluginApi) => void;\n}): DefinedPluginEntry {\n return {\n id: opts.id,\n name: opts.name,\n description: opts.description,\n register: opts.register,\n };\n}\n\nexport function defineChannelPluginEntry<TPlugin extends ChannelPlugin>(opts: {\n id: string;\n name: string;\n description: string;\n plugin: TPlugin;\n setRuntime?: (runtime: PluginRuntime) => void;\n registerFull?: (api: OpenClawPluginApi) => void;\n}): DefinedPluginEntry {\n return definePluginEntry({\n id: opts.id,\n name: opts.name,\n description: opts.description,\n register(api) {\n api.registerChannel({ plugin: opts.plugin });\n if (opts.setRuntime) opts.setRuntime(api.runtime);\n if (api.registrationMode === \"full\" && opts.registerFull) {\n opts.registerFull(api);\n }\n },\n });\n}\n","export interface BounceMessage {\n type: \"message\" | \"accept\" | \"walk\" | \"propose_terms\" | \"counter_terms\" | \"research\";\n content: string;\n terms?: Record<string, any>;\n}\n\nconst SIMPLE_PREFIXES: Record<string, BounceMessage[\"type\"]> = {\n \"[ACCEPT]\": \"accept\",\n \"[WALK]\": \"walk\",\n \"[RESEARCH]\": \"research\",\n};\n\nconst TERMS_PREFIXES: Record<string, BounceMessage[\"type\"]> = {\n \"[TERMS]\": \"propose_terms\",\n \"[COUNTER]\": \"counter_terms\",\n};\n\nexport function parseResponse(text: string): BounceMessage {\n const trimmed = text.trim();\n\n for (const [prefix, type] of Object.entries(SIMPLE_PREFIXES)) {\n if (trimmed.startsWith(prefix)) {\n return { type, content: trimmed.slice(prefix.length).trim() };\n }\n }\n\n for (const [prefix, type] of Object.entries(TERMS_PREFIXES)) {\n if (trimmed.startsWith(prefix)) {\n const rest = trimmed.slice(prefix.length);\n const jsonEnd = rest.indexOf(\"}\");\n if (jsonEnd !== -1) {\n const jsonStr = rest.slice(0, jsonEnd + 1);\n try {\n const terms = JSON.parse(jsonStr);\n const content = rest.slice(jsonEnd + 1).trim();\n return { type, content, terms };\n } catch {\n return { type: \"message\", content: trimmed };\n }\n }\n return { type: \"message\", content: trimmed };\n }\n }\n\n return { type: \"message\", content: trimmed };\n}\n","import { parseResponse } from \"./connector-parser.js\";\nimport { NegotiationSession } from \"./connector-session.js\";\nimport type {\n ChannelPlugin,\n OpenClawConfig,\n PluginLogger,\n SendTextContext,\n} from \"./sdk-types.js\";\n\nconst activeSessions = new Map<string, NegotiationSession>();\n\nexport function getActiveSession(negotiationId: string): NegotiationSession | undefined {\n return activeSessions.get(negotiationId);\n}\n\nexport function setActiveSession(negotiationId: string, session: NegotiationSession): void {\n activeSessions.set(negotiationId, session);\n}\n\nexport function removeActiveSession(negotiationId: string): void {\n const session = activeSessions.get(negotiationId);\n if (session) {\n session.close();\n activeSessions.delete(negotiationId);\n }\n}\n\nexport function getActiveNegotiationId(): string | undefined {\n const entries = [...activeSessions.entries()];\n return entries.length > 0 ? entries[0]![0] : undefined;\n}\n\nexport function createBouncerChannel(logger: PluginLogger): ChannelPlugin {\n return {\n id: \"bouncer\",\n\n meta: {\n id: \"bouncer\",\n label: \"Bouncer Protocol\",\n selectionLabel: \"Bouncer Protocol (Agent Negotiation)\",\n docsPath: \"/channels/bouncer\",\n blurb: \"Real-time agent-to-agent negotiation via the Bouncer Protocol\",\n aliases: [\"bouncer-protocol\"],\n order: 90,\n },\n\n capabilities: {\n chatTypes: [\"direct\"],\n },\n\n config: {\n listAccountIds(cfg: OpenClawConfig): string[] {\n const bouncer = cfg.channels?.bouncer as Record<string, unknown> | undefined;\n if (!bouncer?.agentId) return [];\n return [bouncer.agentId as string];\n },\n\n resolveAccount(cfg: OpenClawConfig, accountId?: string): Record<string, unknown> {\n const bouncer = cfg.channels?.bouncer as Record<string, unknown> | undefined;\n return bouncer ?? { accountId };\n },\n },\n\n outbound: {\n deliveryMode: \"direct\",\n\n async sendText(ctx: SendTextContext): Promise<{ ok: boolean; error?: string }> {\n const negId = ctx.conversationId ?? getActiveNegotiationId();\n if (!negId) {\n return { ok: false, error: \"No active negotiation session\" };\n }\n\n const session = activeSessions.get(negId);\n if (!session) {\n return { ok: false, error: `No session for negotiation ${negId}` };\n }\n\n const parsed = parseResponse(ctx.text);\n\n session.sendThinking();\n\n await new Promise((r) => setTimeout(r, 200));\n\n session.send(parsed);\n logger.info(`[bouncer] Sent ${parsed.type}: ${parsed.content.slice(0, 80)}...`);\n\n return { ok: true };\n },\n },\n };\n}\n","import { EventEmitter } from \"events\";\nimport WebSocket from \"ws\";\n\nlet requestCounter = 0;\n\nexport interface LobbyClientOpts {\n apiUrl: string;\n token: string;\n agentId: string;\n reconnectBaseMs?: number;\n reconnectMaxMs?: number;\n}\n\nexport class LobbyClient extends EventEmitter {\n private ws: WebSocket | null = null;\n private opts: Required<LobbyClientOpts>;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private closed = false;\n private lastHeartbeatAt = 0;\n private watchdogTimer: ReturnType<typeof setInterval> | null = null;\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n\n private static readonly HEARTBEAT_STALE_MS = 45_000;\n private static readonly WATCHDOG_INTERVAL_MS = 15_000;\n private static readonly CLIENT_PING_INTERVAL_MS = 25_000;\n\n constructor(opts: LobbyClientOpts) {\n super();\n this.opts = {\n reconnectBaseMs: 1000,\n reconnectMaxMs: 30_000,\n ...opts,\n };\n }\n\n connect(): Promise<void> {\n this.closed = false;\n return this._connect();\n }\n\n private _connect(): Promise<void> {\n this.stopTimers();\n return new Promise((resolve, reject) => {\n const url = `${this.opts.apiUrl}/v1/agents/${this.opts.agentId}/ws?token=${this.opts.token}`;\n const ws = new WebSocket(url);\n this.ws = ws;\n\n ws.on(\"open\", () => {\n this.reconnectAttempt = 0;\n this.lastHeartbeatAt = Date.now();\n this.startWatchdog();\n this.startClientPing();\n });\n\n ws.on(\"message\", (raw) => {\n try {\n const data = JSON.parse(raw.toString());\n if (data.type === \"connected\") {\n this.lastHeartbeatAt = Date.now();\n this.emit(\"connected\", data);\n resolve();\n } else if (data.type === \"heartbeat\") {\n this.lastHeartbeatAt = Date.now();\n this.emit(\"heartbeat\", data);\n } else if (data.type === \"error\") {\n this.emit(\"error\", new Error(data.error));\n }\n this.emit(data.type, data);\n } catch {}\n });\n\n ws.on(\"close\", () => {\n this.stopTimers();\n if (!this.closed) {\n this.scheduleReconnect();\n }\n });\n\n ws.on(\"error\", (err) => {\n if (this.reconnectAttempt === 0 && ws.readyState === WebSocket.CONNECTING) {\n reject(err);\n }\n });\n });\n }\n\n private startWatchdog() {\n this.watchdogTimer = setInterval(() => {\n if (this.closed) return;\n const staleMs = Date.now() - this.lastHeartbeatAt;\n if (staleMs > LobbyClient.HEARTBEAT_STALE_MS) {\n this.emit(\"stale\", { staleMs });\n this.forceReconnect();\n }\n }, LobbyClient.WATCHDOG_INTERVAL_MS);\n }\n\n private startClientPing() {\n this.pingTimer = setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n try {\n this.ws.ping();\n } catch {}\n }\n }, LobbyClient.CLIENT_PING_INTERVAL_MS);\n }\n\n private stopTimers() {\n if (this.watchdogTimer) { clearInterval(this.watchdogTimer); this.watchdogTimer = null; }\n if (this.pingTimer) { clearInterval(this.pingTimer); this.pingTimer = null; }\n }\n\n private forceReconnect() {\n this.stopTimers();\n if (this.ws) {\n try { this.ws.terminate(); } catch {}\n this.ws = null;\n }\n if (!this.closed) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect() {\n if (this.closed) return;\n const delay = Math.min(\n this.opts.reconnectBaseMs * Math.pow(2, this.reconnectAttempt),\n this.opts.reconnectMaxMs\n );\n this.reconnectAttempt++;\n this.reconnectTimer = setTimeout(() => {\n if (!this.closed) {\n this._connect().catch(() => {});\n }\n }, delay);\n }\n\n accept(negotiationId: string): void {\n this.send({ type: \"accept_negotiation\", negotiation_id: negotiationId });\n }\n\n decline(negotiationId: string, reason?: string): void {\n this.send({ type: \"decline_negotiation\", negotiation_id: negotiationId, reason });\n }\n\n isConnected(): boolean {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;\n if (this.lastHeartbeatAt > 0) {\n const staleMs = Date.now() - this.lastHeartbeatAt;\n if (staleMs > LobbyClient.HEARTBEAT_STALE_MS) return false;\n }\n return true;\n }\n\n send(data: any): boolean {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(data));\n return true;\n }\n return false;\n }\n\n request(msg: Record<string, unknown>, responseType: string, timeoutMs = 30_000): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected()) {\n const staleMs = this.lastHeartbeatAt > 0 ? Date.now() - this.lastHeartbeatAt : -1;\n reject(new Error(`Lobby WS not connected (readyState: ${this.ws?.readyState ?? \"null\"}, lastHeartbeat: ${staleMs}ms ago) — cannot send ${msg.type}`));\n return;\n }\n\n const requestId = `req_${++requestCounter}_${Date.now()}`;\n console.log(`[lobby-request] Sending ${msg.type} with request_id=${requestId}, waiting for ${responseType}`);\n\n const timer = setTimeout(() => {\n const staleMs = this.lastHeartbeatAt > 0 ? Date.now() - this.lastHeartbeatAt : -1;\n console.log(`[lobby-request] TIMEOUT for ${requestId}: readyState=${this.ws?.readyState}, lastHeartbeat=${staleMs}ms ago, listenerCount(${responseType})=${this.listenerCount(responseType)}`);\n cleanup();\n reject(new Error(`WS request timed out waiting for ${responseType} (sent ${msg.type}, waited ${timeoutMs}ms, lastHeartbeat: ${staleMs}ms ago)`));\n }, timeoutMs);\n\n const handler = (data: any) => {\n console.log(`[lobby-request] Got ${responseType} event: request_id=${data.request_id} (waiting for ${requestId})`);\n if (data.request_id === requestId) {\n cleanup();\n if (data.error) {\n reject(new Error(data.error));\n } else {\n resolve(data);\n }\n }\n };\n\n const cleanup = () => {\n clearTimeout(timer);\n this.removeListener(responseType, handler);\n };\n\n this.on(responseType, handler);\n const sent = this.send({ ...msg, request_id: requestId });\n if (!sent) {\n cleanup();\n reject(new Error(`Failed to send ${msg.type} — WS connection dropped between check and send`));\n } else {\n console.log(`[lobby-request] Message sent successfully, readyState=${this.ws?.readyState}`);\n }\n });\n }\n\n close(): void {\n this.closed = true;\n this.stopTimers();\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer);\n if (this.ws) {\n try { this.ws.close(); } catch {}\n this.ws = null;\n }\n }\n}\n","import { EventEmitter } from \"events\";\nimport WebSocket from \"ws\";\n\nexport interface NegotiationSessionOpts {\n apiUrl: string;\n token: string;\n negotiationId: string;\n agentId: string;\n}\n\nexport class NegotiationSession extends EventEmitter {\n private ws: WebSocket | null = null;\n private opts: NegotiationSessionOpts;\n private seenMessageIds = new Set<string>();\n private myAgentId: string;\n\n constructor(opts: NegotiationSessionOpts) {\n super();\n this.opts = opts;\n this.myAgentId = opts.agentId;\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const url = `${this.opts.apiUrl}/v1/negotiations/${this.opts.negotiationId}/ws?token=${this.opts.token}`;\n const ws = new WebSocket(url);\n this.ws = ws;\n\n ws.on(\"message\", (raw) => {\n try {\n const data = JSON.parse(raw.toString());\n\n if (data.type === \"connected\") {\n if (data.agent_id) this.myAgentId = data.agent_id;\n this.emit(\"connected\", data);\n resolve();\n } else if (data.type === \"negotiation_message\") {\n const msg = data.message ?? {\n id: data.id,\n from_agent_id: data.from_agent_id,\n type: data.message_type ?? data.type,\n content: data.content,\n terms: data.terms,\n is_catchup: data.is_catchup,\n created_at: data.created_at,\n };\n\n const msgId = msg.id;\n if (msgId && this.seenMessageIds.has(msgId)) return;\n if (msgId) this.seenMessageIds.add(msgId);\n\n if (msg.from_agent_id === this.myAgentId) return;\n\n this.emit(\"incoming_message\", msg);\n } else if (data.type === \"negotiation_started\") {\n this.emit(\"negotiation_started\", data);\n } else if (data.type === \"negotiation_ended\") {\n this.emit(\"ended\", data);\n this.close();\n } else if (data.type === \"message_ack\") {\n if (data.message?.id) this.seenMessageIds.add(data.message.id);\n this.emit(\"message_ack\", data);\n } else if (data.type === \"agent_thinking\") {\n this.emit(\"agent_thinking\", data);\n } else if (data.type === \"error\") {\n this.emit(\"error\", new Error(data.error));\n }\n } catch {}\n });\n\n ws.on(\"error\", (err) => {\n if (ws.readyState === WebSocket.CONNECTING) {\n reject(err);\n }\n });\n\n ws.on(\"close\", () => {\n this.emit(\"disconnected\");\n });\n });\n }\n\n send(msg: { type: string; content?: string; terms?: object }): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n sendThinking(): void {\n this.send({ type: \"thinking\" });\n }\n\n close(): void {\n if (this.ws) {\n try { this.ws.close(); } catch {}\n this.ws = null;\n }\n }\n}\n","import { LobbyClient } from \"./connector-lobby.js\";\nimport { NegotiationSession } from \"./connector-session.js\";\nimport { parseResponse } from \"./connector-parser.js\";\nimport {\n setActiveSession,\n removeActiveSession,\n} from \"./bouncer-channel.js\";\nimport type { BouncerPluginConfig, NegotiationState } from \"./types.js\";\nimport type {\n OpenClawPluginService,\n OpenClawPluginServiceContext,\n PluginLogger,\n PluginRuntime,\n} from \"./sdk-types.js\";\n\nlet lobbyClient: LobbyClient | null = null;\n\nexport function getLobbyClient(): LobbyClient | null {\n return lobbyClient;\n}\nlet activeNegotiation: NegotiationState | null = null;\nlet pluginRuntime: PluginRuntime | null = null;\n\nfunction resolveAgentFromBindings(cfg: any, channel: string): string | null {\n const bindings = cfg?.bindings;\n if (!Array.isArray(bindings)) return null;\n for (const b of bindings) {\n if (b?.match?.channel === channel && b?.agentId) {\n return b.agentId;\n }\n }\n return null;\n}\n\nlet serviceStarted = false;\n\nexport function setRuntime(rt: PluginRuntime): void {\n pluginRuntime = rt;\n}\n\nexport async function ensureServiceStarted(log: PluginLogger): Promise<void> {\n if (serviceStarted || lobbyClient) return;\n if (!pluginRuntime) return;\n\n try {\n const cfg = await pluginRuntime.config.loadConfig();\n const bouncerCfg = cfg?.channels?.bouncer as Record<string, unknown> | undefined;\n if (!bouncerCfg?.role) return;\n\n const config: BouncerPluginConfig = {\n role: bouncerCfg.role as \"bouncer\" | \"brand\",\n apiUrl: bouncerCfg.apiUrl as string,\n apiKey: bouncerCfg.apiKey as string,\n agentId: bouncerCfg.agentId as string,\n autoAccept: (bouncerCfg.autoAccept as boolean) ?? true,\n llmTimeoutMs: (bouncerCfg.llmTimeoutMs as number) ?? 25_000,\n };\n\n serviceStarted = true;\n log.info(`[bouncer] Self-starting service — role: ${config.role}, agent: ${config.agentId}`);\n\n await startLobby(config, log);\n } catch (err: any) {\n log.error(`[bouncer] Self-start failed: ${err.message}`);\n serviceStarted = false;\n }\n}\n\nexport function getActiveNegotiation(): NegotiationState | null {\n return activeNegotiation;\n}\n\nexport function createBouncerService(config: BouncerPluginConfig): OpenClawPluginService {\n return {\n id: \"bouncer-negotiation-service\",\n\n async start(ctx: OpenClawPluginServiceContext) {\n const log = ctx.logger;\n\n await startLobby(config, log);\n },\n\n async stop() {\n if (lobbyClient) {\n lobbyClient.close();\n lobbyClient = null;\n }\n if (activeNegotiation) {\n removeActiveSession(activeNegotiation.negotiationId);\n activeNegotiation = null;\n }\n },\n };\n}\n\nasync function startLobby(config: BouncerPluginConfig, log: PluginLogger): Promise<void> {\n const wsBase = config.apiUrl.replace(/^http/, \"ws\");\n\n lobbyClient = new LobbyClient({\n apiUrl: wsBase,\n token: config.apiKey,\n agentId: config.agentId,\n reconnectBaseMs: 1_000,\n reconnectMaxMs: 30_000,\n });\n\n lobbyClient.on(\"connected\", () => {\n log.info(`[bouncer] Lobby connected (${config.role} mode).`);\n });\n\n if (config.role === \"bouncer\") {\n lobbyClient.on(\"negotiation_requested\", (data: any) => {\n handleNegotiationRequested(data, config, wsBase, log);\n });\n }\n\n lobbyClient.on(\"heartbeat\", () => {\n log.debug(\"[bouncer] Lobby heartbeat\");\n });\n\n lobbyClient.on(\"stale\", (data: any) => {\n log.warn(`[bouncer] Lobby connection stale (${data.staleMs}ms since last heartbeat) — forcing reconnect`);\n });\n\n try {\n await lobbyClient.connect();\n } catch (err: any) {\n log.error(`[bouncer] Lobby connection failed: ${err.message}`);\n throw err;\n }\n}\n\nasync function handleNegotiationRequested(\n data: any,\n config: BouncerPluginConfig,\n wsBase: string,\n log: PluginLogger,\n): Promise<void> {\n const negId = data.negotiation_id;\n\n if (activeNegotiation) {\n log.info(`[bouncer] Declining ${negId} — already in negotiation ${activeNegotiation.negotiationId}`);\n lobbyClient?.decline(negId, \"busy — already in a negotiation\");\n return;\n }\n\n if (!config.autoAccept) {\n log.info(`[bouncer] Negotiation ${negId} requested but autoAccept is off. Declining.`);\n lobbyClient?.decline(negId, \"auto-accept disabled\");\n return;\n }\n\n log.info(`[bouncer] Accepting negotiation ${negId}`);\n lobbyClient?.accept(negId);\n\n activeNegotiation = {\n negotiationId: negId,\n status: \"pending\",\n otherAgentId: data.brand?.id,\n offerContext: data.offer\n ? { product: data.offer.product, terms: data.offer.terms, opening_message: data.offer.opening_message }\n : undefined,\n };\n\n await connectToNegotiationRoom(negId, config, wsBase, log);\n}\n\nexport async function connectToNegotiationRoom(\n negotiationId: string,\n config: BouncerPluginConfig,\n wsBase: string,\n log: PluginLogger,\n): Promise<void> {\n const session = new NegotiationSession({\n apiUrl: wsBase,\n token: config.apiKey,\n negotiationId,\n agentId: config.agentId,\n });\n\n session.on(\"connected\", () => {\n log.info(`[bouncer] Connected to negotiation room ${negotiationId}`);\n });\n\n session.on(\"negotiation_started\", (data: any) => {\n log.info(`[bouncer] Negotiation ${negotiationId} started`);\n if (activeNegotiation) {\n activeNegotiation.status = \"live\";\n if (data.queue_context) {\n (activeNegotiation as any).queueContext = data.queue_context;\n }\n if (data.relationship) {\n (activeNegotiation as any).relationship = data.relationship;\n }\n }\n });\n\n let dispatching = false;\n session.on(\"incoming_message\", (msg: any) => {\n if (dispatching) {\n log.debug(`[bouncer] Skipping message while dispatch in progress`);\n return;\n }\n log.info(`[bouncer] Message from ${msg.from_agent_id}: ${(msg.content ?? \"\").slice(0, 80)}...`);\n dispatching = true;\n dispatchToAgent(negotiationId, msg, config, session, log).finally(() => {\n dispatching = false;\n });\n });\n\n session.on(\"agent_thinking\", () => {\n log.debug(`[bouncer] Other agent thinking in ${negotiationId}`);\n });\n\n session.on(\"ended\", (data: any) => {\n log.info(`[bouncer] Negotiation ${negotiationId} ended: ${data?.status ?? \"unknown\"}`);\n removeActiveSession(negotiationId);\n activeNegotiation = null;\n });\n\n session.on(\"disconnected\", () => {\n log.warn(`[bouncer] Disconnected from negotiation ${negotiationId}`);\n });\n\n setActiveSession(negotiationId, session);\n\n try {\n await session.connect();\n } catch (err: any) {\n log.error(`[bouncer] Failed to connect to negotiation ${negotiationId}: ${err.message}`);\n removeActiveSession(negotiationId);\n activeNegotiation = null;\n }\n}\n\nasync function dispatchToAgent(\n negotiationId: string,\n msg: any,\n config: BouncerPluginConfig,\n session: NegotiationSession,\n log: PluginLogger,\n): Promise<void> {\n if (!pluginRuntime) {\n log.error(\"[bouncer] Runtime not set — cannot dispatch inbound message to agent\");\n return;\n }\n\n const rt = pluginRuntime;\n\n try {\n const currentCfg = await rt.config.loadConfig();\n\n const resolvedAgent = resolveAgentFromBindings(currentCfg, \"bouncer\");\n if (resolvedAgent) {\n log.info(`[bouncer] Routing negotiation ${negotiationId} to agent: ${resolvedAgent}`);\n }\n\n const msgCtx = rt.channel.reply.finalizeInboundContext({\n Body: msg.content ?? \"\",\n RawBody: msg.content ?? \"\",\n CommandBody: msg.content ?? \"\",\n From: `bouncer:${msg.from_agent_id}`,\n To: `bouncer:${config.agentId}`,\n SessionKey: `bouncer:${negotiationId}`,\n AccountId: config.agentId,\n OriginatingChannel: \"bouncer\",\n OriginatingTo: `bouncer:${msg.from_agent_id}`,\n ChatType: \"direct\",\n SenderName: msg.from_agent_id,\n SenderId: msg.from_agent_id,\n Provider: \"bouncer\",\n Surface: \"bouncer\",\n ConversationLabel: `Negotiation ${negotiationId}`,\n Timestamp: Date.now(),\n CommandAuthorized: true,\n ...(resolvedAgent ? { AgentId: resolvedAgent, TargetAgentId: resolvedAgent, ResolvedAgentId: resolvedAgent } : {}),\n });\n\n await rt.channel.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: msgCtx,\n cfg: currentCfg,\n dispatcherOptions: {\n deliver: async (payload) => {\n const text = payload?.text ?? payload?.body;\n if (!text) return;\n\n const parsed = parseResponse(text);\n session.sendThinking();\n await new Promise((r) => setTimeout(r, 200));\n session.send(parsed);\n log.info(`[bouncer] Agent replied (${parsed.type}): ${parsed.content.slice(0, 80)}...`);\n },\n onReplyStart: () => {\n session.sendThinking();\n },\n },\n });\n } catch (err: any) {\n log.error(`[bouncer] Dispatch failed for negotiation ${negotiationId}: ${err.message}`);\n }\n}\n","export interface BouncerPluginConfig {\n role: \"bouncer\" | \"brand\";\n apiUrl: string;\n apiKey: string;\n agentId: string;\n autoAccept?: boolean;\n llmTimeoutMs?: number;\n}\n\nexport interface NegotiationState {\n negotiationId: string;\n status: \"pending\" | \"live\" | \"ended\";\n otherAgentId?: string;\n offerContext?: {\n product: string;\n terms: string;\n opening_message: string;\n };\n}\n\nexport interface InboundNegotiationMessage {\n negotiationId: string;\n fromAgentId: string;\n type: string;\n content: string;\n terms?: Record<string, unknown>;\n timestamp: string;\n}\n\nexport function resolveConfig(pluginConfig: Record<string, unknown> | undefined): BouncerPluginConfig {\n if (!pluginConfig) throw new Error(\"Bouncer plugin config is required\");\n\n const role = pluginConfig.role as string;\n if (role !== \"bouncer\" && role !== \"brand\") {\n throw new Error(`Invalid role \"${role}\" — must be \"bouncer\" or \"brand\"`);\n }\n\n return {\n role,\n apiUrl: pluginConfig.apiUrl as string,\n apiKey: pluginConfig.apiKey as string,\n agentId: pluginConfig.agentId as string,\n autoAccept: (pluginConfig.autoAccept as boolean) ?? true,\n llmTimeoutMs: (pluginConfig.llmTimeoutMs as number) ?? 25_000,\n };\n}\n\nexport function wsUrl(apiUrl: string): string {\n return apiUrl.replace(/^http/, \"ws\");\n}\n","import type { AgentTool, PluginLogger } from \"./sdk-types.js\";\nimport type { BouncerPluginConfig } from \"./types.js\";\nimport { connectToNegotiationRoom, getLobbyClient } from \"./service.js\";\nimport { wsUrl } from \"./types.js\";\n\nexport function createBrandTools(config: BouncerPluginConfig, logger: PluginLogger): AgentTool[] {\n if (config.role !== \"brand\") return [];\n\n const bouncerBrowse: AgentTool = {\n name: \"bouncer_browse\",\n description:\n \"Browse available Bouncer agents in the directory. Returns a list of bouncers \" +\n \"with their name, listing, tags, and reputation score. Use this to find a \" +\n \"bouncer to target with an offer.\",\n parameters: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n description: \"Max results to return (default: 20)\",\n },\n },\n },\n\n async execute(_toolCallId: string, params: Record<string, unknown>): Promise<unknown> {\n const lobby = getLobbyClient();\n if (!lobby) return { content: [{ type: \"text\", text: JSON.stringify({ error: \"Not connected to lobby\" }) }], details: {} };\n\n try {\n const result = await lobby.request(\n { type: \"browse_bouncers\", limit: params.limit ?? 20 },\n \"browse_bouncers_result\",\n );\n logger.info(`[bouncer] Browse returned ${result.bouncers?.length ?? 0} bouncers`);\n return { content: [{ type: \"text\", text: JSON.stringify(result.bouncers) }], details: {} };\n } catch (err: any) {\n return { content: [{ type: \"text\", text: JSON.stringify({ error: `Browse failed: ${err.message}` }) }], details: {} };\n }\n },\n };\n\n const bouncerProfile: AgentTool = {\n name: \"bouncer_profile\",\n description:\n \"Get the full profile of a specific Bouncer agent, including their listing, \" +\n \"enrichment data, engagement rules, and verified credentials. Use this before \" +\n \"crafting a personalized offer.\",\n parameters: {\n type: \"object\",\n properties: {\n bouncer_id: {\n type: \"string\",\n description: \"The Bouncer agent's UUID\",\n },\n },\n required: [\"bouncer_id\"],\n },\n\n async execute(_toolCallId: string, params: Record<string, unknown>): Promise<unknown> {\n const lobby = getLobbyClient();\n if (!lobby) return { content: [{ type: \"text\", text: JSON.stringify({ error: \"Not connected to lobby\" }) }], details: {} };\n\n try {\n const result = await lobby.request(\n { type: \"get_profile\", bouncer_id: params.bouncer_id },\n \"get_profile_result\",\n );\n if (result.error) return { content: [{ type: \"text\", text: JSON.stringify({ error: result.error }) }], details: {} };\n return { content: [{ type: \"text\", text: JSON.stringify(result.profile) }], details: {} };\n } catch (err: any) {\n return { content: [{ type: \"text\", text: JSON.stringify({ error: `Profile fetch failed: ${err.message}` }) }], details: {} };\n }\n },\n };\n\n const bouncerOffer: AgentTool = {\n name: \"bouncer_offer\",\n description:\n \"Submit an offer to a Bouncer agent and create a negotiation. This sends your \" +\n \"offer and automatically connects you to the negotiation room when the bouncer \" +\n \"accepts. Returns the offer_id and negotiation_id.\",\n parameters: {\n type: \"object\",\n properties: {\n bouncer_id: {\n type: \"string\",\n description: \"The target Bouncer's UUID\",\n },\n product: {\n type: \"string\",\n description: \"Product or service being offered\",\n },\n terms: {\n type: \"string\",\n description: \"Deal terms (e.g. '$20 credit + free delivery')\",\n },\n opening_message: {\n type: \"string\",\n description: \"Personalized opening message to the Bouncer\",\n },\n priority_bid: {\n type: \"number\",\n description: \"Priority bid in USDC (e.g. 2.0)\",\n },\n arena: {\n type: \"boolean\",\n description: \"Practice mode — no real USDC (default: false)\",\n },\n },\n required: [\"bouncer_id\", \"product\", \"terms\", \"opening_message\", \"priority_bid\"],\n },\n\n async execute(_toolCallId: string, params: Record<string, unknown>): Promise<unknown> {\n const lobby = getLobbyClient();\n const wrap = (obj: unknown) => ({ content: [{ type: \"text\", text: JSON.stringify(obj) }], details: {} });\n\n if (!lobby) {\n logger.error(\"[bouncer] bouncer_offer: getLobbyClient() returned null — lobby not initialized\");\n return wrap({ error: \"Not connected to lobby\" });\n }\n\n const connected = lobby.isConnected();\n logger.info(`[bouncer] bouncer_offer: lobby.isConnected() = ${connected}`);\n if (!connected) {\n logger.error(\"[bouncer] bouncer_offer: lobby exists but isConnected() is false — WS may be reconnecting\");\n return wrap({ error: \"Lobby WS not connected — may be reconnecting. Try again in a few seconds.\" });\n }\n\n const bouncerId = params.bouncer_id as string;\n logger.info(`[bouncer] bouncer_offer PARAMS: ${JSON.stringify(params)}`);\n\n try {\n logger.info(`[bouncer] Submitting offer to ${bouncerId}`);\n const sendStart = Date.now();\n\n const offerResult = await lobby.request(\n {\n type: \"submit_offer\",\n bouncer_id: bouncerId,\n product: params.product,\n terms: params.terms,\n opening_message: params.opening_message,\n priority_bid: params.priority_bid,\n arena: params.arena ?? false,\n },\n \"submit_offer_result\",\n );\n\n logger.info(`[bouncer] submit_offer response in ${Date.now() - sendStart}ms`);\n\n if (offerResult.error) {\n return wrap({ error: `Offer submission failed: ${offerResult.error}` });\n }\n\n const offerId = offerResult.offer_id;\n logger.info(`[bouncer] Offer submitted: ${offerId}`);\n\n logger.info(`[bouncer] Creating negotiation for offer ${offerId}`);\n const negResult = await lobby.request(\n { type: \"create_negotiation\", offer_id: offerId, bouncer_id: bouncerId },\n \"create_negotiation_result\",\n );\n\n if (negResult.error) {\n return wrap({ error: `Negotiation creation failed: ${negResult.error}`, offer_id: offerId });\n }\n\n const negotiationId = negResult.negotiation_id;\n logger.info(`[bouncer] Negotiation created: ${negotiationId}`);\n\n logger.info(`[bouncer] Waiting for bouncer to accept (via WS)...`);\n const accepted = await waitForAcceptanceWS(negotiationId, 120_000);\n\n if (!accepted) {\n return wrap({ status: \"declined_or_timeout\", offer_id: offerId, negotiation_id: negotiationId });\n }\n\n logger.info(`[bouncer] Accepted! Connecting to negotiation room...`);\n await connectToNegotiationRoom(negotiationId, config, wsUrl(config.apiUrl), logger);\n\n return wrap({\n status: \"connected\",\n offer_id: offerId,\n negotiation_id: negotiationId,\n message: \"Connected to negotiation room. Incoming messages will appear as chat messages.\",\n });\n } catch (err: any) {\n return wrap({ error: `Offer flow failed: ${err.message}` });\n }\n },\n };\n\n return [bouncerBrowse, bouncerProfile, bouncerOffer];\n}\n\nfunction waitForAcceptanceWS(negotiationId: string, timeoutMs: number): Promise<boolean> {\n return new Promise((resolve) => {\n const lobby = getLobbyClient();\n if (!lobby) {\n resolve(false);\n return;\n }\n\n const timer = setTimeout(() => {\n cleanup();\n resolve(false);\n }, timeoutMs);\n\n const onAccepted = (data: any) => {\n if (data.negotiation_id === negotiationId) {\n cleanup();\n resolve(true);\n }\n };\n\n const onDeclined = (data: any) => {\n if (data.negotiation_id === negotiationId) {\n cleanup();\n resolve(false);\n }\n };\n\n const cleanup = () => {\n clearTimeout(timer);\n lobby.removeListener(\"negotiation_accepted\", onAccepted);\n lobby.removeListener(\"negotiation_declined\", onDeclined);\n };\n\n lobby.on(\"negotiation_accepted\", onAccepted);\n lobby.on(\"negotiation_declined\", onDeclined);\n });\n}\n","import { definePluginEntry } from \"./src/sdk-types.js\";\nimport { createBouncerChannel } from \"./src/bouncer-channel.js\";\nimport { createBouncerService, setRuntime, ensureServiceStarted } from \"./src/service.js\";\nimport { createBrandTools } from \"./src/tools.js\";\nimport { resolveConfig } from \"./src/types.js\";\nimport type { OpenClawPluginApi, PluginLogger } from \"./src/sdk-types.js\";\n\nlet pluginLogger: PluginLogger = {\n info: console.log,\n warn: console.warn,\n error: console.error,\n debug: () => {},\n};\n\nconst channel = createBouncerChannel(pluginLogger);\n\nexport default definePluginEntry({\n id: \"bouncer\",\n name: \"Bouncer Protocol\",\n description: \"Agent-to-agent negotiation channel via the Bouncer Protocol. \" +\n \"Handles WebSocket lifecycle, heartbeats, echo filtering, and protocol \" +\n \"message formatting so the LLM only deals with plain text.\",\n\n register(api: OpenClawPluginApi) {\n const logger = api.logger ?? pluginLogger;\n pluginLogger = logger;\n\n api.registerChannel({ plugin: channel });\n setRuntime(api.runtime);\n\n if (api.runtime.logging) {\n const child = api.runtime.logging.getChildLogger(\"bouncer\");\n if (child) pluginLogger = child;\n }\n\n const bouncerConfig = resolveChannelConfig(api);\n if (!bouncerConfig) {\n logger.warn(\"[bouncer] No bouncer channel config found — will self-start from runtime config.\");\n setTimeout(() => {\n ensureServiceStartedWithTools(api, pluginLogger).catch((err: any) => {\n pluginLogger.error(`[bouncer] Deferred start failed: ${err.message}`);\n });\n }, 2_000);\n return;\n }\n\n const config = resolveConfig(bouncerConfig);\n logger.info(`[bouncer] Registering plugin — role: ${config.role}, agent: ${config.agentId}`);\n\n api.registerService(createBouncerService(config));\n\n const tools = createBrandTools(config, logger);\n for (const tool of tools) {\n api.registerTool(tool, { name: tool.name });\n }\n\n logger.info(`[bouncer] Plugin registered. Role: ${config.role}`);\n if (config.role === \"bouncer\") {\n logger.info(\"[bouncer] Lobby service will start on gateway boot.\");\n } else {\n logger.info(\"[bouncer] Brand tools registered: bouncer_browse, bouncer_profile, bouncer_offer\");\n }\n },\n});\n\nasync function ensureServiceStartedWithTools(api: OpenClawPluginApi, log: PluginLogger): Promise<void> {\n try {\n const cfg = await api.runtime.config.loadConfig();\n const bouncerCfg = cfg?.channels?.bouncer as Record<string, unknown> | undefined;\n if (!bouncerCfg?.role) {\n log.warn(\"[bouncer] Deferred start: no channels.bouncer.role found in runtime config.\");\n return;\n }\n\n const config = resolveConfig(bouncerCfg);\n log.info(`[bouncer] Deferred registration — role: ${config.role}, agent: ${config.agentId}`);\n\n api.registerService(createBouncerService(config));\n\n const tools = createBrandTools(config, log);\n for (const tool of tools) {\n api.registerTool(tool, { name: tool.name });\n }\n\n if (config.role === \"bouncer\") {\n log.info(\"[bouncer] Lobby service registered via deferred start.\");\n } else {\n log.info(\"[bouncer] Brand tools registered via deferred start: bouncer_browse, bouncer_profile, bouncer_offer\");\n }\n\n await ensureServiceStarted(log);\n } catch (err: any) {\n log.error(`[bouncer] Deferred start failed: ${err.message}`);\n }\n}\n\nfunction resolveChannelConfig(api: OpenClawPluginApi): Record<string, unknown> | null {\n const fromChannels = api.config?.channels?.bouncer as Record<string, unknown> | undefined;\n if (fromChannels && fromChannels.role) return fromChannels;\n\n if (api.pluginConfig && Object.keys(api.pluginConfig).length > 0) {\n return api.pluginConfig;\n }\n\n if (fromChannels && !fromChannels.role) {\n pluginLogger.warn(\n \"[bouncer] channels.bouncer exists but has no 'role' — check config. \" +\n \"Required: role, apiUrl, apiKey, agentId\"\n );\n }\n\n return null;\n}\n"],"mappings":"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","names":["EventEmitter","WebSocket","channel"]}
|
package/package.json
CHANGED