@mulmobridge/client 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -49,13 +49,43 @@ client.onPush((ev) => {
49
49
 
50
50
  ## Ecosystem
51
51
 
52
- Part of the `@mulmobridge/*` package family:
52
+ Part of the [`@mulmobridge/*`](https://www.npmjs.com/~mulmobridge) package family.
53
53
 
54
- - **@mulmobridge/protocol** — shared types and constants
55
- - **@mulmobridge/client** — this package
56
- - **@mulmobridge/cli** — interactive terminal bridge
57
- - **@mulmobridge/telegram** — Telegram bot bridge
58
- - **@mulmobridge/chat-service** — server-side chat service
54
+ **Shared libraries:**
55
+
56
+ - [`@mulmobridge/client`](https://www.npmjs.com/package/@mulmobridge/client) — socket.io client library used by every bridge below ← **this package**
57
+ - [`@mulmobridge/protocol`](https://www.npmjs.com/package/@mulmobridge/protocol) — wire types and constants
58
+ - [`@mulmobridge/chat-service`](https://www.npmjs.com/package/@mulmobridge/chat-service) — server-side relay + session store
59
+ - [`@mulmobridge/relay`](https://www.npmjs.com/package/@mulmobridge/relay) — Cloudflare Workers webhook proxy
60
+ - [`@mulmobridge/mock-server`](https://www.npmjs.com/package/@mulmobridge/mock-server) — mock server for local bridge development
61
+
62
+ **Bridges** (one npm package per platform):
63
+
64
+ - [`@mulmobridge/bluesky`](https://www.npmjs.com/package/@mulmobridge/bluesky) — Bluesky DMs over atproto
65
+ - [`@mulmobridge/chatwork`](https://www.npmjs.com/package/@mulmobridge/chatwork) — Chatwork (Japanese business chat)
66
+ - [`@mulmobridge/cli`](https://www.npmjs.com/package/@mulmobridge/cli) — interactive terminal bridge
67
+ - [`@mulmobridge/discord`](https://www.npmjs.com/package/@mulmobridge/discord) — Discord bot via Gateway
68
+ - [`@mulmobridge/email`](https://www.npmjs.com/package/@mulmobridge/email) — IMAP poll + SMTP reply, threading preserved
69
+ - [`@mulmobridge/google-chat`](https://www.npmjs.com/package/@mulmobridge/google-chat) — Google Chat via MulmoBridge relay
70
+ - [`@mulmobridge/irc`](https://www.npmjs.com/package/@mulmobridge/irc) — IRC (Libera, Freenode, custom)
71
+ - [`@mulmobridge/line`](https://www.npmjs.com/package/@mulmobridge/line) — LINE Messaging API via MulmoBridge relay
72
+ - [`@mulmobridge/line-works`](https://www.npmjs.com/package/@mulmobridge/line-works) — LINE Works (enterprise LINE)
73
+ - [`@mulmobridge/mastodon`](https://www.npmjs.com/package/@mulmobridge/mastodon) — Mastodon DMs + mentions
74
+ - [`@mulmobridge/matrix`](https://www.npmjs.com/package/@mulmobridge/matrix) — Matrix / Element
75
+ - [`@mulmobridge/mattermost`](https://www.npmjs.com/package/@mulmobridge/mattermost) — Mattermost
76
+ - [`@mulmobridge/messenger`](https://www.npmjs.com/package/@mulmobridge/messenger) — Facebook Messenger via MulmoBridge relay
77
+ - [`@mulmobridge/nostr`](https://www.npmjs.com/package/@mulmobridge/nostr) — Nostr NIP-04 encrypted DMs
78
+ - [`@mulmobridge/rocketchat`](https://www.npmjs.com/package/@mulmobridge/rocketchat) — Rocket.Chat
79
+ - [`@mulmobridge/signal`](https://www.npmjs.com/package/@mulmobridge/signal) — Signal via signal-cli-rest-api
80
+ - [`@mulmobridge/slack`](https://www.npmjs.com/package/@mulmobridge/slack) — Slack Socket Mode
81
+ - [`@mulmobridge/teams`](https://www.npmjs.com/package/@mulmobridge/teams) — Microsoft Teams via Bot Framework
82
+ - [`@mulmobridge/telegram`](https://www.npmjs.com/package/@mulmobridge/telegram) — Telegram bot
83
+ - [`@mulmobridge/twilio-sms`](https://www.npmjs.com/package/@mulmobridge/twilio-sms) — SMS via Twilio Programmable Messaging
84
+ - [`@mulmobridge/viber`](https://www.npmjs.com/package/@mulmobridge/viber) — Viber Public Account bots
85
+ - [`@mulmobridge/webhook`](https://www.npmjs.com/package/@mulmobridge/webhook) — generic HTTP webhook bridge
86
+ - [`@mulmobridge/whatsapp`](https://www.npmjs.com/package/@mulmobridge/whatsapp) — WhatsApp Cloud API via MulmoBridge relay
87
+ - [`@mulmobridge/xmpp`](https://www.npmjs.com/package/@mulmobridge/xmpp) — XMPP / Jabber
88
+ - [`@mulmobridge/zulip`](https://www.npmjs.com/package/@mulmobridge/zulip) — Zulip
59
89
 
60
90
  ## License
61
91
 
package/dist/index.d.ts CHANGED
@@ -2,4 +2,5 @@ export { createBridgeClient, requireBearerToken, type MessageAck, type PushEvent
2
2
  export { readBridgeToken, TOKEN_FILE_PATH } from "./token.js";
3
3
  export { readBridgeEnvOptions } from "./options.js";
4
4
  export { chunkText } from "./text.js";
5
+ export { formatAckReply } from "./reply.js";
5
6
  export { mimeFromExtension, isImageMime, isPdfMime, isSupportedAttachmentMime, isNativeAttachmentMime, parseDataUrl, buildDataUrl, type ParsedDataUrl, } from "./mime.js";
package/dist/index.js CHANGED
@@ -3,4 +3,5 @@ export { createBridgeClient, requireBearerToken } from "./client.js";
3
3
  export { readBridgeToken, TOKEN_FILE_PATH } from "./token.js";
4
4
  export { readBridgeEnvOptions } from "./options.js";
5
5
  export { chunkText } from "./text.js";
6
+ export { formatAckReply } from "./reply.js";
6
7
  export { mimeFromExtension, isImageMime, isPdfMime, isSupportedAttachmentMime, isNativeAttachmentMime, parseDataUrl, buildDataUrl, } from "./mime.js";
package/dist/mime.d.ts CHANGED
@@ -1,14 +1,17 @@
1
1
  /** Infer MIME type from a file extension (case-insensitive).
2
2
  * Returns the fallback if the extension is not recognised. */
3
3
  export declare function mimeFromExtension(ext: string, fallback?: string): string;
4
- /** True when the MIME type is an image Claude can see via vision. */
5
- export declare function isImageMime(mimeType: string): boolean;
4
+ /** True when the MIME type is an image Claude can see via vision.
5
+ * Tolerates `undefined` so callers can pass an attachment's optional
6
+ * `mimeType` directly. */
7
+ export declare function isImageMime(mimeType: string | undefined): boolean;
6
8
  /** True when the MIME type is a PDF document Claude can read natively
7
- * via `type: "document"` content blocks. */
8
- export declare function isPdfMime(mimeType: string): boolean;
9
+ * via `type: "document"` content blocks. Tolerates `undefined`. */
10
+ export declare function isPdfMime(mimeType: string | undefined): boolean;
9
11
  /** True when the attachment can be sent to Claude directly as a
10
- * native content block (image or PDF) — no conversion needed. */
11
- export declare function isNativeAttachmentMime(mimeType: string): boolean;
12
+ * native content block (image or PDF) — no conversion needed.
13
+ * Tolerates `undefined`. */
14
+ export declare function isNativeAttachmentMime(mimeType: string | undefined): boolean;
12
15
  export declare const isSupportedAttachmentMime: typeof isNativeAttachmentMime;
13
16
  export interface ParsedDataUrl {
14
17
  mimeType: string;
package/dist/mime.js CHANGED
@@ -31,17 +31,20 @@ const EXT_TO_MIME = {
31
31
  export function mimeFromExtension(ext, fallback = "application/octet-stream") {
32
32
  return EXT_TO_MIME[ext.toLowerCase()] ?? fallback;
33
33
  }
34
- /** True when the MIME type is an image Claude can see via vision. */
34
+ /** True when the MIME type is an image Claude can see via vision.
35
+ * Tolerates `undefined` so callers can pass an attachment's optional
36
+ * `mimeType` directly. */
35
37
  export function isImageMime(mimeType) {
36
- return mimeType.startsWith("image/");
38
+ return typeof mimeType === "string" && mimeType.startsWith("image/");
37
39
  }
38
40
  /** True when the MIME type is a PDF document Claude can read natively
39
- * via `type: "document"` content blocks. */
41
+ * via `type: "document"` content blocks. Tolerates `undefined`. */
40
42
  export function isPdfMime(mimeType) {
41
43
  return mimeType === "application/pdf";
42
44
  }
43
45
  /** True when the attachment can be sent to Claude directly as a
44
- * native content block (image or PDF) — no conversion needed. */
46
+ * native content block (image or PDF) — no conversion needed.
47
+ * Tolerates `undefined`. */
45
48
  export function isNativeAttachmentMime(mimeType) {
46
49
  return isImageMime(mimeType) || isPdfMime(mimeType);
47
50
  }
package/dist/options.d.ts CHANGED
@@ -5,9 +5,18 @@
5
5
  * Precedence when the same key resolves from both forms:
6
6
  * transport-specific wins over shared.
7
7
  *
8
+ * Transport ids with dashes (`google-chat`, `line-works`,
9
+ * `twilio-sms`, …) are normalised to underscores when building the
10
+ * env prefix: `google-chat` → `GOOGLE_CHAT_BRIDGE_*`. Dashes in env
11
+ * var names break shells, so `_` is the portable convention.
12
+ *
8
13
  * Example:
9
14
  * SLACK_BRIDGE_DEFAULT_ROLE=slack
10
15
  * BRIDGE_DEFAULT_ROLE=general
11
16
  * → `{ defaultRole: "slack" }`
17
+ *
18
+ * GOOGLE_CHAT_BRIDGE_DEFAULT_ROLE=support
19
+ * (with transportId="google-chat")
20
+ * → `{ defaultRole: "support" }`
12
21
  */
13
22
  export declare function readBridgeEnvOptions(transportId: string, env: Readonly<Record<string, string | undefined>>): Record<string, string>;
package/dist/options.js CHANGED
@@ -48,13 +48,22 @@ function matchBridgePrefix(name, transportPrefix) {
48
48
  * Precedence when the same key resolves from both forms:
49
49
  * transport-specific wins over shared.
50
50
  *
51
+ * Transport ids with dashes (`google-chat`, `line-works`,
52
+ * `twilio-sms`, …) are normalised to underscores when building the
53
+ * env prefix: `google-chat` → `GOOGLE_CHAT_BRIDGE_*`. Dashes in env
54
+ * var names break shells, so `_` is the portable convention.
55
+ *
51
56
  * Example:
52
57
  * SLACK_BRIDGE_DEFAULT_ROLE=slack
53
58
  * BRIDGE_DEFAULT_ROLE=general
54
59
  * → `{ defaultRole: "slack" }`
60
+ *
61
+ * GOOGLE_CHAT_BRIDGE_DEFAULT_ROLE=support
62
+ * (with transportId="google-chat")
63
+ * → `{ defaultRole: "support" }`
55
64
  */
56
65
  export function readBridgeEnvOptions(transportId, env) {
57
- const transportPrefix = `${transportId.toUpperCase()}_BRIDGE_`;
66
+ const transportPrefix = `${transportId.toUpperCase().replace(/-/g, "_")}_BRIDGE_`;
58
67
  const shared = {};
59
68
  const specific = {};
60
69
  for (const [name, value] of Object.entries(env)) {
@@ -0,0 +1,8 @@
1
+ import type { MessageAck } from "./client.js";
2
+ /**
3
+ * Format a `MessageAck` as a single user-facing string.
4
+ *
5
+ * - `ok` ack → `reply` content (or empty string if absent).
6
+ * - Failed ack → `"Error[ (status)]: <error or 'unknown'>"`.
7
+ */
8
+ export declare function formatAckReply(ack: MessageAck): string;
package/dist/reply.js ADDED
@@ -0,0 +1,19 @@
1
+ // Shared reply formatting for bridges.
2
+ //
3
+ // Every bridge converts a `MessageAck` from `BridgeClient.send()`
4
+ // into a single string to send back over its native transport. The
5
+ // happy-path / error-path shape is identical across bridges
6
+ // (LINE / Slack / Teams / Mastodon / XMPP all do the same thing
7
+ // modulo the send call), so the formatting belongs here.
8
+ /**
9
+ * Format a `MessageAck` as a single user-facing string.
10
+ *
11
+ * - `ok` ack → `reply` content (or empty string if absent).
12
+ * - Failed ack → `"Error[ (status)]: <error or 'unknown'>"`.
13
+ */
14
+ export function formatAckReply(ack) {
15
+ if (ack.ok)
16
+ return ack.reply ?? "";
17
+ const status = ack.status ? ` (${ack.status})` : "";
18
+ return `Error${status}: ${ack.error ?? "unknown"}`;
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mulmobridge/client",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Socket.io client library for MulmoBridge — shared by all bridge implementations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -45,11 +45,11 @@
45
45
  "license": "MIT",
46
46
  "author": "Receptron Team",
47
47
  "dependencies": {
48
- "@mulmobridge/protocol": "^0.1.0",
48
+ "@mulmobridge/protocol": "^0.1.4",
49
49
  "socket.io-client": "^4.0.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@types/node": "^25.6.0",
52
+ "@types/node": "^26.1.0",
53
53
  "typescript": "^6.0.3"
54
54
  }
55
55
  }