@mutirolabs/openclaw-brain 0.1.1 → 0.2.1

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +70 -3
  2. package/README.md +44 -217
  3. package/dist/index.js +20 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/src/actions.js +40 -0
  6. package/dist/src/actions.js.map +1 -0
  7. package/dist/src/agent-tools.js +547 -0
  8. package/dist/src/agent-tools.js.map +1 -0
  9. package/dist/src/bridge-client.js +172 -0
  10. package/dist/src/bridge-client.js.map +1 -0
  11. package/dist/src/bridge-messages.js +226 -0
  12. package/dist/src/bridge-messages.js.map +1 -0
  13. package/dist/src/bridge-protocol.js +42 -0
  14. package/dist/src/bridge-protocol.js.map +1 -0
  15. package/dist/src/bridge-session.js +279 -0
  16. package/dist/src/bridge-session.js.map +1 -0
  17. package/dist/src/channel.js +167 -0
  18. package/dist/src/channel.js.map +1 -0
  19. package/dist/src/channel.runtime.js +422 -0
  20. package/dist/src/channel.runtime.js.map +1 -0
  21. package/dist/src/config.js +61 -0
  22. package/dist/src/config.js.map +1 -0
  23. package/dist/src/inbound.js +92 -0
  24. package/dist/src/inbound.js.map +1 -0
  25. package/dist/src/live-snapshot.js +151 -0
  26. package/dist/src/live-snapshot.js.map +1 -0
  27. package/dist/src/outbound.js +205 -0
  28. package/dist/src/outbound.js.map +1 -0
  29. package/dist/src/setup-surface.js +252 -0
  30. package/dist/src/setup-surface.js.map +1 -0
  31. package/dist/src/signal-forwarder.js +119 -0
  32. package/dist/src/signal-forwarder.js.map +1 -0
  33. package/docs/assets/mutiro-openclaw-ui.png +0 -0
  34. package/docs/guides/manage-allowlist.md +3 -3
  35. package/docs/guides/use-openclaw-as-brain.md +15 -15
  36. package/index.ts +1 -1
  37. package/openclaw.plugin.json +5 -3
  38. package/package.json +9 -7
  39. package/src/agent-tools.ts +3 -3
  40. package/src/bridge-client.ts +1 -2
  41. package/src/bridge-messages.ts +2 -2
  42. package/src/bridge-protocol.ts +2 -2
  43. package/src/bridge-session.ts +2 -2
  44. package/src/channel.runtime.ts +54 -3
  45. package/src/channel.ts +61 -2
  46. package/src/outbound.ts +5 -7
  47. package/src/setup-surface.ts +39 -11
@@ -0,0 +1,422 @@
1
+ // Heavy runtime surface for the Mutiro channel plugin. Owns the registry of
2
+ // active BridgeSession instances keyed by account and serves inbound/outbound
3
+ // calls from the plugin's gateway and outbound adapters.
4
+ //
5
+ // Keeping this file separate from `channel.ts` means the light plugin entry
6
+ // does not pull the NDJSON + child_process machinery into gateway startup.
7
+ import { recordInboundSession } from "openclaw/plugin-sdk/conversation-runtime";
8
+ import { recordInboundSessionAndDispatchReply } from "openclaw/plugin-sdk/inbound-reply-dispatch";
9
+ import { dispatchReplyWithBufferedBlockDispatcher, finalizeInboundContext, } from "openclaw/plugin-sdk/reply-dispatch-runtime";
10
+ import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
11
+ import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
12
+ import { startBridgeSession } from "./bridge-session.js";
13
+ import { normalizeOutputText } from "./bridge-messages.js";
14
+ const sessions = new Map();
15
+ // Crash-backoff state per account. Repeated crashes escalate the delay so we
16
+ // don't thrash the gateway's restart loop when the host is consistently
17
+ // failing (bad config, missing credential, host crash on boot, etc.). The
18
+ // streak resets when the last crash is older than `CRASH_STREAK_RESET_MS`,
19
+ // so a host that ran healthy for a while then crashed once starts over at
20
+ // the shortest backoff.
21
+ const CRASH_BACKOFF_MS = [1_000, 2_000, 5_000, 15_000, 60_000];
22
+ const CRASH_STREAK_RESET_MS = 5 * 60_000;
23
+ const crashState = new Map();
24
+ const sessionKey = (channel, accountId) => `${channel}:${accountId}`;
25
+ const requireSessionForAccount = (accountId) => {
26
+ const session = sessions.get(sessionKey("mutiro", accountId ?? "default"));
27
+ if (!session) {
28
+ throw new Error(`mutiro channel: no active bridge session for account "${accountId ?? "default"}". gateway.startAccount must run first.`);
29
+ }
30
+ return session;
31
+ };
32
+ // Public accessor used by agent tools that need to reach the active bridge
33
+ // session without throwing when the channel is not running yet.
34
+ export const getMutiroBridgeSession = (accountId) => sessions.get(sessionKey("mutiro", accountId ?? "default"));
35
+ /**
36
+ * Runs the agent against a delegated task prompt and returns the
37
+ * accumulated reply text. Used by `task.request`, which — unlike
38
+ * `message.observed` — expects the full reply text inside the
39
+ * `ChatBridgeTaskResult` envelope instead of on the outbound bridge.
40
+ *
41
+ * We reuse the same reply-dispatch path as buildDeliverBridge but swap
42
+ * the deliver callback: instead of shipping chunks via bridge.message.send
43
+ * we accumulate them into a buffer the caller returns to the host.
44
+ *
45
+ * Tool side-effects (mutiro_send_voice_message, mutiro_send_card, etc.)
46
+ * still fire normally through their own execute() paths — only the
47
+ * agent's plain reply text is captured for the task result.
48
+ */
49
+ const buildResolveTaskRequest = (ctx) => async (params) => {
50
+ const senderUsername = (params.username ?? "").trim() || "system";
51
+ const route = resolveAgentRoute({
52
+ cfg: ctx.cfg,
53
+ channel: "mutiro",
54
+ accountId: params.accountId,
55
+ peer: { kind: "direct", id: senderUsername },
56
+ });
57
+ const storePath = resolveStorePath(ctx.cfg.session?.store, { agentId: route.agentId });
58
+ const messageSid = params.requestId ?? `task-${Date.now()}`;
59
+ const ctxPayload = finalizeInboundContext({
60
+ Body: params.prompt,
61
+ BodyForAgent: params.prompt,
62
+ RawBody: params.prompt,
63
+ CommandBody: params.prompt,
64
+ From: senderUsername,
65
+ To: params.conversationId,
66
+ SessionKey: route.sessionKey,
67
+ AccountId: route.accountId ?? params.accountId,
68
+ ChatType: "direct",
69
+ ConversationLabel: params.conversationId,
70
+ SenderId: senderUsername,
71
+ Provider: "mutiro",
72
+ Surface: "mutiro",
73
+ MessageSid: messageSid,
74
+ MessageSidFull: messageSid,
75
+ Timestamp: Date.now(),
76
+ OriginatingChannel: "mutiro",
77
+ OriginatingTo: params.conversationId,
78
+ });
79
+ const accumulator = [];
80
+ const dispatchPromise = recordInboundSessionAndDispatchReply({
81
+ cfg: ctx.cfg,
82
+ channel: "mutiro",
83
+ accountId: params.accountId,
84
+ agentId: route.agentId,
85
+ routeSessionKey: route.sessionKey,
86
+ storePath,
87
+ ctxPayload,
88
+ recordInboundSession,
89
+ dispatchReplyWithBufferedBlockDispatcher,
90
+ deliver: async (payload) => {
91
+ const chunk = String(payload.text ?? "");
92
+ if (chunk)
93
+ accumulator.push(chunk);
94
+ },
95
+ onRecordError: (err) => ctx.log?.warn?.(`mutiro: task record error: ${formatError(err)}`),
96
+ onDispatchError: (err, info) => ctx.log?.warn?.(`mutiro: task dispatch error (${info.kind}): ${formatError(err)}`),
97
+ });
98
+ // Honor timeout_ms: whichever finishes first, use what accumulated.
99
+ // If the dispatch ran past the deadline we return partial output and
100
+ // let the background promise drain; the host already has its answer.
101
+ if (params.timeoutMs && params.timeoutMs > 0) {
102
+ await Promise.race([
103
+ dispatchPromise,
104
+ new Promise((resolve) => setTimeout(resolve, params.timeoutMs)),
105
+ ]);
106
+ }
107
+ else {
108
+ await dispatchPromise;
109
+ }
110
+ return normalizeOutputText(accumulator.join(""));
111
+ };
112
+ const buildDeliverBridge = (ctx) => async (inbound) => {
113
+ const session = requireSessionForAccount(inbound.accountId);
114
+ // Resolve the routing / session / ctxPayload pieces directly from the
115
+ // public plugin-sdk helpers rather than relying on `ctx.channelRuntime`
116
+ // to carry the full runtime surface (it does not for bundled channels).
117
+ const route = resolveAgentRoute({
118
+ cfg: ctx.cfg,
119
+ channel: "mutiro",
120
+ accountId: inbound.accountId,
121
+ peer: { kind: "direct", id: inbound.senderUsername },
122
+ });
123
+ const storePath = resolveStorePath(ctx.cfg.session?.store, { agentId: route.agentId });
124
+ const target = {
125
+ conversationId: inbound.conversationId,
126
+ replyToMessageId: inbound.messageId,
127
+ };
128
+ const { createSignalForwarder } = await import("./signal-forwarder.js");
129
+ const signals = createSignalForwarder(session, target);
130
+ // Fire a THINKING pulse immediately so the user sees feedback while
131
+ // dispatch warms up (model selection, memory loads, etc.). Subsequent
132
+ // on* callbacks replace it with more specific signals.
133
+ signals.thinking();
134
+ const mediaPaths = inbound.mediaPaths ?? [];
135
+ const mediaTypes = inbound.mediaTypes ?? [];
136
+ const ctxPayload = finalizeInboundContext({
137
+ Body: inbound.text,
138
+ BodyForAgent: inbound.text,
139
+ RawBody: inbound.text,
140
+ CommandBody: inbound.text,
141
+ From: inbound.senderUsername,
142
+ To: inbound.conversationId,
143
+ SessionKey: route.sessionKey,
144
+ AccountId: route.accountId ?? inbound.accountId,
145
+ ChatType: "direct",
146
+ ConversationLabel: inbound.conversationId,
147
+ SenderId: inbound.senderUsername,
148
+ Provider: "mutiro",
149
+ Surface: "mutiro",
150
+ MessageSid: inbound.messageId,
151
+ MessageSidFull: inbound.messageId,
152
+ Timestamp: Date.now(),
153
+ OriginatingChannel: "mutiro",
154
+ OriginatingTo: inbound.conversationId,
155
+ ...(mediaPaths.length > 0
156
+ ? {
157
+ MediaPath: mediaPaths[0],
158
+ MediaPaths: mediaPaths,
159
+ MediaType: mediaTypes[0],
160
+ MediaTypes: mediaTypes,
161
+ }
162
+ : {}),
163
+ });
164
+ await recordInboundSessionAndDispatchReply({
165
+ cfg: ctx.cfg,
166
+ channel: "mutiro",
167
+ accountId: inbound.accountId,
168
+ agentId: route.agentId,
169
+ routeSessionKey: route.sessionKey,
170
+ storePath,
171
+ ctxPayload,
172
+ recordInboundSession,
173
+ dispatchReplyWithBufferedBlockDispatcher,
174
+ deliver: async (payload) => {
175
+ const text = normalizeOutputText(String(payload.text ?? ""));
176
+ if (!text)
177
+ return;
178
+ await session.outbound.sendText(target, text);
179
+ },
180
+ // replyOptions taps OpenClaw's mid-turn hooks to forward progress
181
+ // into Mutiro's signal stream. Each on* callback maps to a specific
182
+ // SIGNAL_TYPE_* so the user sees "searching web", "remembering",
183
+ // "writing response" pills instead of a single static "thinking".
184
+ replyOptions: {
185
+ onAssistantMessageStart: () => signals.typing(),
186
+ onReasoningStream: () => signals.reasoning(),
187
+ onToolStart: (payload) => signals.toolStart(payload.name, payload.phase),
188
+ // onItemEvent carries richer detail than onToolStart — `title` is
189
+ // resolved from tool args (e.g. "read src/x.ts"). Refine only on
190
+ // the start phase; "end"/"update" would thrash the pill.
191
+ onItemEvent: (payload) => {
192
+ if (payload.phase && payload.phase !== "start")
193
+ return;
194
+ signals.itemStart({
195
+ name: payload.name,
196
+ title: payload.title,
197
+ phase: payload.phase,
198
+ });
199
+ },
200
+ onCompactionStart: () => signals.compactionStart(),
201
+ onCompactionEnd: () => signals.compactionEnd(),
202
+ onPlanUpdate: (payload) => signals.planUpdate(payload.title),
203
+ },
204
+ onRecordError: (err) => ctx.log?.warn?.(`mutiro: record session error: ${formatError(err)}`),
205
+ onDispatchError: (err, info) => ctx.log?.warn?.(`mutiro: dispatch error (${info.kind}): ${formatError(err)}`),
206
+ });
207
+ // Close the signal stream and the host-owned turn lifecycle.
208
+ // TURN_COMPLETE clears any lingering pill in the Mutiro UI; endTurn
209
+ // releases the host-side pending turn regardless of whether visible
210
+ // replies were emitted.
211
+ signals.turnComplete();
212
+ session.outbound.endTurn(target);
213
+ };
214
+ export const startMutiroAccount = async (ctx) => {
215
+ const key = sessionKey("mutiro", ctx.accountId);
216
+ const existing = sessions.get(key);
217
+ if (existing) {
218
+ return;
219
+ }
220
+ const { account } = ctx;
221
+ if (!account.configured || !account.config.agentDir) {
222
+ ctx.log?.warn?.(`mutiro: account "${ctx.accountId}" is not configured (missing agentDir)`);
223
+ return;
224
+ }
225
+ // The gateway expects startAccount to stay pending for the lifetime of the
226
+ // channel. Resolving early is interpreted as "channel exited" and triggers
227
+ // an auto-restart loop. We block on exit-or-abort via this deferred.
228
+ let settleLifecycle = () => { };
229
+ const lifecycle = new Promise((resolve) => {
230
+ settleLifecycle = resolve;
231
+ });
232
+ const session = await startBridgeSession({
233
+ accountId: ctx.accountId,
234
+ agentDir: account.config.agentDir,
235
+ clientName: account.config.clientName,
236
+ requestedOptionalCapabilities: account.config.requestedOptionalCapabilities,
237
+ deliver: buildDeliverBridge(ctx),
238
+ resolveTaskRequest: buildResolveTaskRequest(ctx),
239
+ resolveLiveSnapshot: async (params) => {
240
+ // Lazy-load the snapshot module so startup stays clean and the
241
+ // plugin-sdk/config-runtime surface is only touched when the host
242
+ // actually requests a live handoff (i.e. a voice call starts).
243
+ const { buildLiveSnapshot } = await import("./live-snapshot.js");
244
+ return buildLiveSnapshot({
245
+ cfg: ctx.cfg,
246
+ accountId: params.accountId,
247
+ conversationId: params.conversationId,
248
+ callerUsername: params.username,
249
+ callId: params.callId,
250
+ agentUsername: session?.getAgentUsername() ?? "",
251
+ });
252
+ },
253
+ logger: ctx.log
254
+ ? {
255
+ info: ctx.log.info,
256
+ warn: ctx.log.warn,
257
+ error: ctx.log.error,
258
+ }
259
+ : undefined,
260
+ onHostExit: (code) => {
261
+ sessions.delete(key);
262
+ const now = Date.now();
263
+ const isAbort = ctx.abortSignal.aborted;
264
+ const isCleanExit = code === 0 || isAbort;
265
+ if (isCleanExit) {
266
+ crashState.delete(ctx.accountId);
267
+ ctx.log?.info?.(`mutiro: host (${ctx.accountId}) exited with code ${code}${isAbort ? " (abort)" : ""}`);
268
+ ctx.setStatus({
269
+ ...ctx.getStatus(),
270
+ running: false,
271
+ connected: false,
272
+ lastDisconnect: { at: now, status: code ?? undefined },
273
+ });
274
+ settleLifecycle();
275
+ return;
276
+ }
277
+ // Unexpected exit: track the streak, compute backoff, and hold the
278
+ // lifecycle promise until the delay elapses. The gateway's restart
279
+ // loop won't fire until we settle, so this delay is the effective
280
+ // backoff without touching gateway internals.
281
+ const prior = crashState.get(ctx.accountId);
282
+ const streak = prior && now - prior.lastCrashAt < CRASH_STREAK_RESET_MS ? prior.count + 1 : 1;
283
+ crashState.set(ctx.accountId, { count: streak, lastCrashAt: now });
284
+ const delayMs = CRASH_BACKOFF_MS[Math.min(streak - 1, CRASH_BACKOFF_MS.length - 1)];
285
+ ctx.log?.warn?.(`mutiro: host (${ctx.accountId}) exited unexpectedly with code ${code}; ` +
286
+ `restarting in ${Math.round(delayMs / 1000)}s (attempt ${streak})`);
287
+ ctx.setStatus({
288
+ ...ctx.getStatus(),
289
+ running: false,
290
+ connected: false,
291
+ restartPending: true,
292
+ reconnectAttempts: streak,
293
+ lastDisconnect: {
294
+ at: now,
295
+ status: code ?? undefined,
296
+ error: `exit_code=${code ?? "null"}`,
297
+ },
298
+ });
299
+ setTimeout(() => {
300
+ settleLifecycle();
301
+ }, delayMs);
302
+ },
303
+ });
304
+ sessions.set(key, session);
305
+ ctx.setStatus({
306
+ ...ctx.getStatus(),
307
+ running: true,
308
+ connected: true,
309
+ lastConnectedAt: Date.now(),
310
+ lastStartAt: Date.now(),
311
+ });
312
+ const onAbort = () => {
313
+ void stopSession(key).finally(settleLifecycle);
314
+ };
315
+ if (ctx.abortSignal.aborted) {
316
+ onAbort();
317
+ }
318
+ else {
319
+ ctx.abortSignal.addEventListener("abort", onAbort, { once: true });
320
+ }
321
+ await lifecycle;
322
+ };
323
+ export const stopMutiroAccount = async (ctx) => {
324
+ await stopSession(sessionKey("mutiro", ctx.accountId));
325
+ ctx.setStatus({
326
+ ...ctx.getStatus(),
327
+ running: false,
328
+ connected: false,
329
+ lastStopAt: Date.now(),
330
+ });
331
+ };
332
+ const stopSession = async (key) => {
333
+ const session = sessions.get(key);
334
+ if (!session)
335
+ return;
336
+ sessions.delete(key);
337
+ await session.shutdown();
338
+ };
339
+ export const sendMutiroText = async (ctx) => {
340
+ const session = requireSessionForAccount(ctx.accountId);
341
+ await session.outbound.sendText({
342
+ conversationId: ctx.to,
343
+ replyToMessageId: ctx.replyToId ?? ctx.threadId?.toString() ?? "",
344
+ }, ctx.text);
345
+ return {
346
+ channel: "mutiro",
347
+ messageId: ctx.replyToId ?? `mutiro-${Date.now()}`,
348
+ conversationId: ctx.to,
349
+ };
350
+ };
351
+ export const sendMutiroMedia = async (ctx) => {
352
+ if (!ctx.mediaUrl) {
353
+ throw new Error("sendMedia called without mediaUrl");
354
+ }
355
+ const session = requireSessionForAccount(ctx.accountId);
356
+ await session.outbound.sendFile({
357
+ conversationId: ctx.to,
358
+ replyToMessageId: ctx.replyToId ?? ctx.threadId?.toString() ?? "",
359
+ }, {
360
+ filePath: ctx.mediaUrl,
361
+ caption: ctx.text,
362
+ });
363
+ return {
364
+ channel: "mutiro",
365
+ messageId: ctx.replyToId ?? `mutiro-${Date.now()}`,
366
+ conversationId: ctx.to,
367
+ };
368
+ };
369
+ const formatError = (err) => err instanceof Error ? err.message : JSON.stringify(err);
370
+ // Dispatcher for ChannelMessageActionAdapter.handleAction. Declared here so
371
+ // the heavy runtime does the bridge work, and the light `actions.ts` file
372
+ // stays a pure control-plane adapter that loads this lazily.
373
+ export const handleMutiroMessageAction = async (params) => {
374
+ const session = requireSessionForAccount(params.accountId);
375
+ if (params.action === "react") {
376
+ const messageId = params.readStringArg(params.params, "messageId", "message_id", "to");
377
+ const emoji = params.readStringArg(params.params, "emoji", "reaction");
378
+ if (!messageId) {
379
+ return {
380
+ content: [{ type: "text", text: "react requires a messageId." }],
381
+ details: { ok: false, reason: "missing_message_id" },
382
+ };
383
+ }
384
+ if (!emoji) {
385
+ return {
386
+ content: [{ type: "text", text: "react requires an emoji." }],
387
+ details: { ok: false, reason: "missing_emoji" },
388
+ };
389
+ }
390
+ try {
391
+ const raw = await session.outbound.react({ messageId, emoji });
392
+ return {
393
+ content: [{ type: "text", text: `Reacted ${emoji} to ${messageId}.` }],
394
+ details: { ok: true, raw },
395
+ };
396
+ }
397
+ catch (err) {
398
+ const message = formatError(err);
399
+ return {
400
+ content: [{ type: "text", text: `Failed to react: ${message}` }],
401
+ details: { ok: false, reason: "bridge_error", error: message },
402
+ };
403
+ }
404
+ }
405
+ return {
406
+ content: [
407
+ {
408
+ type: "text",
409
+ text: `Unsupported Mutiro message action: ${params.action}`,
410
+ },
411
+ ],
412
+ details: { ok: false, reason: "unsupported_action", action: params.action },
413
+ };
414
+ };
415
+ // Barrel export consumed by the plugin entry via `loadBundledEntryExportSync`.
416
+ export const mutiroChannelRuntime = {
417
+ startMutiroAccount,
418
+ stopMutiroAccount,
419
+ sendMutiroText,
420
+ sendMutiroMedia,
421
+ };
422
+ //# sourceMappingURL=channel.runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.runtime.js","sourceRoot":"","sources":["../../src/channel.runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ // Mutiro channel configuration and per-account resolution.
2
+ //
3
+ // The channel supports one or more named accounts; each account pins a
4
+ // specific Mutiro agent directory that `mutiro agent host --mode=bridge`
5
+ // should run from. We reuse OpenClaw's `createScopedChannelConfigAdapter` so
6
+ // the account lifecycle (list/default/resolve) flows through the same shape
7
+ // the Plugin SDK already knows how to drive.
8
+ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
9
+ export { DEFAULT_ACCOUNT_ID };
10
+ const readMutiroSection = (cfg) => {
11
+ const channels = cfg.channels;
12
+ return channels?.mutiro;
13
+ };
14
+ const resolveAccountConfig = (cfg, accountId) => {
15
+ const section = readMutiroSection(cfg);
16
+ if (!section)
17
+ return undefined;
18
+ if (accountId === DEFAULT_ACCOUNT_ID && section.agentDir) {
19
+ return {
20
+ agentDir: section.agentDir,
21
+ clientName: section.clientName,
22
+ requestedOptionalCapabilities: section.requestedOptionalCapabilities,
23
+ enabled: section.enabled,
24
+ };
25
+ }
26
+ return section.accounts?.[accountId];
27
+ };
28
+ export const listMutiroAccountIds = (cfg) => {
29
+ const section = readMutiroSection(cfg);
30
+ const named = Object.keys(section?.accounts ?? {});
31
+ if (named.length > 0)
32
+ return named;
33
+ return section?.agentDir ? [DEFAULT_ACCOUNT_ID] : [];
34
+ };
35
+ export const resolveDefaultMutiroAccountId = (cfg) => {
36
+ const ids = listMutiroAccountIds(cfg);
37
+ return ids[0] ?? DEFAULT_ACCOUNT_ID;
38
+ };
39
+ export const resolveMutiroAccount = (cfg, accountId) => {
40
+ const id = accountId || resolveDefaultMutiroAccountId(cfg);
41
+ const base = resolveAccountConfig(cfg, id) ?? { agentDir: "" };
42
+ const configured = Boolean(base.agentDir);
43
+ return {
44
+ accountId: id,
45
+ enabled: base.enabled !== false,
46
+ configured,
47
+ name: base.name,
48
+ config: base,
49
+ };
50
+ };
51
+ // Build the ChannelConfigAdapter directly. The helpers in
52
+ // `channel-config-helpers` expect allowlist and clear-base-field accessors
53
+ // that Mutiro does not use, so we wire the two required hooks manually.
54
+ export const mutiroConfigAdapter = {
55
+ listAccountIds: listMutiroAccountIds,
56
+ resolveAccount: resolveMutiroAccount,
57
+ defaultAccountId: resolveDefaultMutiroAccountId,
58
+ isEnabled: (account) => account.enabled,
59
+ isConfigured: (account) => account.configured,
60
+ };
61
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,6CAA6C;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,EAAE,kBAAkB,EAAE,CAAC;AA2B9B,MAAM,iBAAiB,GAAG,CAAC,GAAmB,EAAoC,EAAE;IAClF,MAAM,QAAQ,GAAI,GAA8C,CAAC,QAAQ,CAAC;IAC1E,OAAO,QAAQ,EAAE,MAA0C,CAAC;AAC9D,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAC3B,GAAmB,EACnB,SAAiB,EACgB,EAAE;IACnC,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAE/B,IAAI,SAAS,KAAK,kBAAkB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzD,OAAO;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,6BAA6B,EAAE,OAAO,CAAC,6BAA6B;YACpE,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAmB,EAAY,EAAE;IACpE,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,GAAmB,EAAU,EAAE;IAC3E,MAAM,GAAG,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC;AACtC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,GAAmB,EACnB,SAAyB,EACF,EAAE;IACzB,MAAM,EAAE,GAAG,SAAS,IAAI,6BAA6B,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,oBAAoB,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO;QACL,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,KAAK;QAC/B,UAAU;QACV,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI;KACb,CAAC;AACJ,CAAC,CAAC;AAEF,0DAA0D;AAC1D,2EAA2E;AAC3E,wEAAwE;AACxE,MAAM,CAAC,MAAM,mBAAmB,GAAmD;IACjF,cAAc,EAAE,oBAAoB;IACpC,cAAc,EAAE,oBAAoB;IACpC,gBAAgB,EAAE,6BAA6B;IAC/C,SAAS,EAAE,CAAC,OAA8B,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO;IAC9D,YAAY,EAAE,CAAC,OAA8B,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU;CACrE,CAAC"}
@@ -0,0 +1,92 @@
1
+ // Translates bridge observed messages into the inbound delivery the OpenClaw
2
+ // gateway expects from a channel plugin. The runtime installs a single inbound
3
+ // delivery callback during plugin startup; this module's job is to shape each
4
+ // observed bridge envelope into that callback's input.
5
+ import { saveMediaBuffer } from "openclaw/plugin-sdk/browser-setup-tools";
6
+ import { buildObservedTurn, isSelfEventMessage } from "./bridge-messages.js";
7
+ /**
8
+ * The bridge delivers image attachments inline as base64 under
9
+ * `envelope.payload.images`. We persist each one into OpenClaw's media
10
+ * directory via `saveMediaBuffer`, which stages under `~/.openclaw/media/`
11
+ * — the only root OpenClaw's sandbox staging policy accepts. Writing to
12
+ * `os.tmpdir()` silently fails staging and leaves the agent with only a
13
+ * text path reference, so the bytes never reach the model.
14
+ */
15
+ const persistInlineImages = async (images) => {
16
+ if (!Array.isArray(images) || images.length === 0) {
17
+ return { paths: [], types: [] };
18
+ }
19
+ const paths = [];
20
+ const types = [];
21
+ for (const entry of images) {
22
+ if (!entry?.data)
23
+ continue;
24
+ try {
25
+ const saved = await saveMediaBuffer(Buffer.from(entry.data, "base64"), entry.mime_type, "inbound", undefined, entry.filename);
26
+ paths.push(saved.path);
27
+ types.push(saved.contentType ?? entry.mime_type ?? "application/octet-stream");
28
+ }
29
+ catch {
30
+ // Best-effort: skip a single bad attachment rather than aborting the turn.
31
+ }
32
+ }
33
+ return { paths, types };
34
+ };
35
+ /**
36
+ * Shapes a bridge envelope into the OpenClaw inbound message the gateway
37
+ * delivers to core. Returns the observed turn it extracted (useful for the
38
+ * caller to key session state) or null when the envelope was self-authored or
39
+ * did not carry a deliverable message.
40
+ */
41
+ export const deliverObservedEnvelope = async (envelope, route) => {
42
+ if (envelope.type === "event.message" && isSelfEventMessage(envelope, route.agentUsername)) {
43
+ return null;
44
+ }
45
+ // Reactions and other bare events are now delivered to OpenClaw like any
46
+ // other observation. The agent may choose to stay silent, which today
47
+ // surfaces "Agent couldn't generate a response" — acceptable trade-off
48
+ // for letting the agent actually see reactions happen. If OpenClaw grows
49
+ // a "silent turn is ok" dispatch option later, filter these through that.
50
+ const turn = buildObservedTurn(envelope);
51
+ if (!turn) {
52
+ return null;
53
+ }
54
+ const { paths, types } = await persistInlineImages(envelope.payload?.images);
55
+ // attachment_context is the host's narrative of downloaded attachments:
56
+ // [SYSTEM: Downloaded 1 file(s) to your workspace:
57
+ // • nf-2976.pdf → /Users/.../Downloads/nf-2976.pdf (PDF, 450 KB)]
58
+ // For PDFs/docs this is the ONLY pointer the agent gets — it needs the
59
+ // path to invoke `read` or a doc-extraction tool. We earlier stripped
60
+ // this string because the host's image probe produced noisy "0x0 pixels"
61
+ // metadata that fooled vision models. Image turns now route bytes
62
+ // through MediaPaths instead, so attachment_context is pure signal for
63
+ // non-image attachments. Append only when the message carries file-type
64
+ // parts; skip for image-only or text-only turns.
65
+ const hasFileParts = extractHasFileParts(envelope.payload?.message);
66
+ const contextText = (envelope.payload?.attachment_context ?? "").trim();
67
+ const bodyText = hasFileParts && contextText
68
+ ? turn.text
69
+ ? `${turn.text}\n\n${contextText}`
70
+ : contextText
71
+ : turn.text;
72
+ await route.deliver({
73
+ channelId: "mutiro",
74
+ accountId: route.accountId,
75
+ conversationId: turn.conversationId,
76
+ messageId: turn.messageId,
77
+ replyToMessageId: turn.replyToMessageId,
78
+ senderUsername: turn.senderUsername,
79
+ text: bodyText,
80
+ rawMessage: envelope.payload?.message,
81
+ attachmentContext: envelope.payload?.attachment_context,
82
+ ...(paths.length > 0 ? { mediaPaths: paths, mediaTypes: types } : {}),
83
+ });
84
+ return turn;
85
+ };
86
+ const extractHasFileParts = (message) => {
87
+ if (!message)
88
+ return false;
89
+ const parts = Array.isArray(message.parts) ? message.parts : [];
90
+ return parts.some((part) => part?.type === "file");
91
+ };
92
+ //# sourceMappingURL=inbound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../src/inbound.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,uDAAuD;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAG1E,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AA8B7E;;;;;;;GAOG;AACH,MAAM,mBAAmB,GAAG,KAAK,EAC/B,MAAiC,EACc,EAAE;IACjD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAClC,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,EAAE,IAAI;YAAE,SAAS;QAC3B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,eAAe,CACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,EACjC,KAAK,CAAC,SAAS,EACf,SAAS,EACT,SAAS,EACT,KAAK,CAAC,QAAQ,CACf,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS,IAAI,0BAA0B,CAAC,CAAC;QACjF,CAAC;QAAC,MAAM,CAAC;YACP,2EAA2E;QAC7E,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,QAO2C,EAC3C,KAAmB,EACW,EAAE;IAChC,IAAI,QAAQ,CAAC,IAAI,KAAK,eAAe,IAAI,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yEAAyE;IACzE,sEAAsE;IACtE,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE7E,wEAAwE;IACxE,qDAAqD;IACrD,qEAAqE;IACrE,uEAAuE;IACvE,sEAAsE;IACtE,yEAAyE;IACzE,kEAAkE;IAClE,uEAAuE;IACvE,wEAAwE;IACxE,iDAAiD;IACjD,MAAM,YAAY,GAAG,mBAAmB,CACtC,QAAQ,CAAC,OAAO,EAAE,OAA2D,CAC9E,CAAC;IACF,MAAM,WAAW,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxE,MAAM,QAAQ,GACZ,YAAY,IAAI,WAAW;QACzB,CAAC,CAAC,IAAI,CAAC,IAAI;YACT,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,OAAO,WAAW,EAAE;YAClC,CAAC,CAAC,WAAW;QACf,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAEhB,MAAM,KAAK,CAAC,OAAO,CAAC;QAClB,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO;QACrC,iBAAiB,EAAE,QAAQ,CAAC,OAAO,EAAE,kBAAkB;QACvD,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtE,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAC1B,OAAyD,EAChD,EAAE;IACX,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC;AACrD,CAAC,CAAC"}