@mulmobridge/protocol 0.1.3 → 1.0.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/README.md CHANGED
@@ -18,7 +18,7 @@ npm install @mulmobridge/protocol
18
18
  | `CHAT_SOCKET_PATH` | Socket.io endpoint path (`"/ws/chat"`) |
19
19
  | `ChatSocketEvent` | Union type of socket event names |
20
20
  | `CHAT_SERVICE_ROUTES` | REST endpoint patterns for the bridge API |
21
- | `Attachment` | File attachment interface (`mimeType` + base64 `data` + optional `filename`) |
21
+ | `Attachment` | File attachment interface — either inline base64 `data` or workspace `path`, with optional `mimeType`/`filename` |
22
22
 
23
23
  ## Usage
24
24
 
@@ -58,6 +58,47 @@ const attachment: Attachment = {
58
58
  | [@mulmobridge/cli](https://www.npmjs.com/package/@mulmobridge/cli) | CLI bridge |
59
59
  | [@mulmobridge/telegram](https://www.npmjs.com/package/@mulmobridge/telegram) | Telegram bridge |
60
60
 
61
+ ## Ecosystem
62
+
63
+ Part of the [`@mulmobridge/*`](https://www.npmjs.com/~mulmobridge) package family.
64
+
65
+ **Shared libraries:**
66
+
67
+ - [`@mulmobridge/client`](https://www.npmjs.com/package/@mulmobridge/client) — socket.io client library used by every bridge below
68
+ - [`@mulmobridge/protocol`](https://www.npmjs.com/package/@mulmobridge/protocol) — wire types and constants ← **this package**
69
+ - [`@mulmobridge/chat-service`](https://www.npmjs.com/package/@mulmobridge/chat-service) — server-side relay + session store
70
+ - [`@mulmobridge/relay`](https://www.npmjs.com/package/@mulmobridge/relay) — Cloudflare Workers webhook proxy
71
+ - [`@mulmobridge/mock-server`](https://www.npmjs.com/package/@mulmobridge/mock-server) — mock server for local bridge development
72
+
73
+ **Bridges** (one npm package per platform):
74
+
75
+ - [`@mulmobridge/bluesky`](https://www.npmjs.com/package/@mulmobridge/bluesky) — Bluesky DMs over atproto
76
+ - [`@mulmobridge/chatwork`](https://www.npmjs.com/package/@mulmobridge/chatwork) — Chatwork (Japanese business chat)
77
+ - [`@mulmobridge/cli`](https://www.npmjs.com/package/@mulmobridge/cli) — interactive terminal bridge
78
+ - [`@mulmobridge/discord`](https://www.npmjs.com/package/@mulmobridge/discord) — Discord bot via Gateway
79
+ - [`@mulmobridge/email`](https://www.npmjs.com/package/@mulmobridge/email) — IMAP poll + SMTP reply, threading preserved
80
+ - [`@mulmobridge/google-chat`](https://www.npmjs.com/package/@mulmobridge/google-chat) — Google Chat via MulmoBridge relay
81
+ - [`@mulmobridge/irc`](https://www.npmjs.com/package/@mulmobridge/irc) — IRC (Libera, Freenode, custom)
82
+ - [`@mulmobridge/line`](https://www.npmjs.com/package/@mulmobridge/line) — LINE Messaging API via MulmoBridge relay
83
+ - [`@mulmobridge/line-works`](https://www.npmjs.com/package/@mulmobridge/line-works) — LINE Works (enterprise LINE)
84
+ - [`@mulmobridge/mastodon`](https://www.npmjs.com/package/@mulmobridge/mastodon) — Mastodon DMs + mentions
85
+ - [`@mulmobridge/matrix`](https://www.npmjs.com/package/@mulmobridge/matrix) — Matrix / Element
86
+ - [`@mulmobridge/mattermost`](https://www.npmjs.com/package/@mulmobridge/mattermost) — Mattermost
87
+ - [`@mulmobridge/messenger`](https://www.npmjs.com/package/@mulmobridge/messenger) — Facebook Messenger via MulmoBridge relay
88
+ - [`@mulmobridge/nostr`](https://www.npmjs.com/package/@mulmobridge/nostr) — Nostr NIP-04 encrypted DMs
89
+ - [`@mulmobridge/rocketchat`](https://www.npmjs.com/package/@mulmobridge/rocketchat) — Rocket.Chat
90
+ - [`@mulmobridge/signal`](https://www.npmjs.com/package/@mulmobridge/signal) — Signal via signal-cli-rest-api
91
+ - [`@mulmobridge/slack`](https://www.npmjs.com/package/@mulmobridge/slack) — Slack Socket Mode
92
+ - [`@mulmobridge/teams`](https://www.npmjs.com/package/@mulmobridge/teams) — Microsoft Teams via Bot Framework
93
+ - [`@mulmobridge/telegram`](https://www.npmjs.com/package/@mulmobridge/telegram) — Telegram bot
94
+ - [`@mulmobridge/twilio-sms`](https://www.npmjs.com/package/@mulmobridge/twilio-sms) — SMS via Twilio Programmable Messaging
95
+ - [`@mulmobridge/viber`](https://www.npmjs.com/package/@mulmobridge/viber) — Viber Public Account bots
96
+ - [`@mulmobridge/webhook`](https://www.npmjs.com/package/@mulmobridge/webhook) — generic HTTP webhook bridge
97
+ - [`@mulmobridge/whatsapp`](https://www.npmjs.com/package/@mulmobridge/whatsapp) — WhatsApp Cloud API via MulmoBridge relay
98
+ - [`@mulmobridge/xmpp`](https://www.npmjs.com/package/@mulmobridge/xmpp) — XMPP / Jabber
99
+ - [`@mulmobridge/zulip`](https://www.npmjs.com/package/@mulmobridge/zulip) — Zulip
100
+
101
+
61
102
  ## License
62
103
 
63
104
  MIT — [Receptron Team](https://github.com/receptron)
@@ -1,8 +1,15 @@
1
1
  export interface Attachment {
2
- /** IANA media type, e.g. "image/png". */
3
- mimeType: string;
4
- /** Raw base64-encoded payload (no `data:` prefix, no whitespace). */
5
- data: string;
2
+ /** IANA media type, e.g. "image/png". Optional when only `path` is
3
+ * set — the server infers the type from the path extension. */
4
+ mimeType?: string;
5
+ /** Raw base64-encoded payload (no `data:` prefix, no whitespace).
6
+ * Required when `path` is not set. */
7
+ data?: string;
8
+ /** Workspace-relative path to a file the server can read. Required
9
+ * when `data` is not set. Must live under one of the allowed roots
10
+ * (e.g. `artifacts/images/...`, `data/attachments/...`); the
11
+ * server enforces this with `safeResolve`. */
12
+ path?: string;
6
13
  /** Optional original filename. Untrusted — sanitise before use on disk. */
7
14
  filename?: string;
8
15
  }
@@ -1,2 +1,18 @@
1
1
  // File attachment schema for chat messages (images, documents, etc.).
2
+ //
3
+ // One of `data` (inline base64 bytes) or `path` (workspace-relative
4
+ // path) MUST be set. The two carriers exist because:
5
+ //
6
+ // - Bridge clients (Telegram, LINE, Mastodon, ...) ship raw bytes
7
+ // over the wire, so they populate `data`.
8
+ // - The Vue UI uploads paste/drop and sidebar-pick images to disk
9
+ // before send (so the data layer is path-first), so it populates
10
+ // `path`. The server reads bytes from disk on receipt.
11
+ //
12
+ // Server-internal normalisation (e.g. `prepareRequestExtras` in the
13
+ // agent route) loads bytes for path-only entries before downstream
14
+ // consumers see the array, so anything reading `data` after that
15
+ // boundary can rely on it being present. Outside that boundary
16
+ // (i.e. when first received), readers MUST runtime-check which
17
+ // carrier is set and handle the path case explicitly.
2
18
  export {};
package/dist/events.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export declare const EVENT_TYPES: {
2
2
  readonly status: "status";
3
3
  readonly text: "text";
4
+ readonly skill: "skill";
4
5
  readonly toolCall: "tool_call";
5
6
  readonly toolCallResult: "tool_call_result";
6
7
  readonly toolResult: "tool_result";
7
- readonly switchRole: "switch_role";
8
8
  readonly error: "error";
9
9
  readonly claudeSessionId: "claude_session_id";
10
10
  readonly sessionFinished: "session_finished";
@@ -27,6 +27,7 @@ export declare const GENERATION_KINDS: {
27
27
  readonly characterImage: "characterImage";
28
28
  readonly beatAudio: "beatAudio";
29
29
  readonly movie: "movie";
30
+ readonly pdf: "pdf";
30
31
  };
31
32
  export type GenerationKind = (typeof GENERATION_KINDS)[keyof typeof GENERATION_KINDS];
32
33
  export interface GenerationEvent {
package/dist/events.js CHANGED
@@ -6,10 +6,18 @@
6
6
  export const EVENT_TYPES = {
7
7
  status: "status",
8
8
  text: "text",
9
+ // #1218 — assistant text whose content is the body of an invoked
10
+ // SKILL.md, synthesised by Claude CLI when the model calls the
11
+ // `Skill` tool. Tagged separately from `text` so the canvas can
12
+ // collapse it (skill bodies are huge and not actual prose).
13
+ // Detected server-side via the preceding tool_call's
14
+ // toolName === "Skill" (structural — survives Claude CLI body-text
15
+ // changes), then enriched with `skillName` / `skillScope` /
16
+ // `skillPath` resolved against `discoverSkills()`.
17
+ skill: "skill",
9
18
  toolCall: "tool_call",
10
19
  toolCallResult: "tool_call_result",
11
20
  toolResult: "tool_result",
12
- switchRole: "switch_role",
13
21
  error: "error",
14
22
  claudeSessionId: "claude_session_id",
15
23
  sessionFinished: "session_finished",
@@ -31,6 +39,7 @@ export const GENERATION_KINDS = {
31
39
  characterImage: "characterImage",
32
40
  beatAudio: "beatAudio",
33
41
  movie: "movie",
42
+ pdf: "pdf",
34
43
  };
35
44
  /**
36
45
  * Stable map-key for a generation: the triple (kind, filePath, key).
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { EVENT_TYPES, type EventType, GENERATION_KINDS, type GenerationKind, type GenerationEvent, type PendingGeneration, generationKey } from "./events.js";
2
- export { CHAT_SOCKET_PATH, CHAT_SOCKET_EVENTS, type ChatSocketEvent } from "./socket.js";
2
+ export { CHAT_SOCKET_PATH, CHAT_SOCKET_EVENTS, type ChatSocketEvent, type BridgeHandshakeAuth, type BridgeOptions } from "./socket.js";
3
3
  export { type Attachment } from "./attachment.js";
4
4
  export { CHAT_SERVICE_ROUTES } from "./routes.js";
package/dist/socket.d.ts CHANGED
@@ -9,3 +9,30 @@ export declare const CHAT_SOCKET_EVENTS: {
9
9
  readonly textChunk: "textChunk";
10
10
  };
11
11
  export type ChatSocketEvent = (typeof CHAT_SOCKET_EVENTS)[keyof typeof CHAT_SOCKET_EVENTS];
12
+ /**
13
+ * Bridge → host-app option bag carried on the handshake.
14
+ *
15
+ * Values are restricted to flat primitives (string / number /
16
+ * boolean). The restriction serves two purposes:
17
+ *
18
+ * 1. The wire contract is explicit — no surprise nested objects
19
+ * slip through to the host app's callback where a downstream
20
+ * merge might reintroduce prototype-pollution risk.
21
+ * 2. The scrape-from-env path produces strings anyway, so the
22
+ * ceiling is already flat primitives in practice.
23
+ *
24
+ * Protocol does not interpret any keys — bridges and host apps agree
25
+ * on names (`defaultRole`, …) out of band.
26
+ */
27
+ export type BridgeOptions = Readonly<Record<string, string | number | boolean>>;
28
+ /**
29
+ * Shape of `socket.handshake.auth` on the bridge chat socket. The
30
+ * server validates `transportId` + `token`; `options` is the opaque-
31
+ * but-primitive bag forwarded to the host application's startChat
32
+ * callback. See `plans/done/feat-bridge-options-passthrough.md`.
33
+ */
34
+ export interface BridgeHandshakeAuth {
35
+ transportId: string;
36
+ token?: string;
37
+ options?: BridgeOptions;
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mulmobridge/protocol",
3
- "version": "0.1.3",
3
+ "version": "1.0.0",
4
4
  "description": "Shared types and constants for the MulmoBridge protocol",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",