@mulmobridge/protocol 0.1.2 → 0.1.4

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/events.d.ts CHANGED
@@ -10,5 +10,56 @@ export declare const EVENT_TYPES: {
10
10
  readonly sessionFinished: "session_finished";
11
11
  readonly sessionMeta: "session_meta";
12
12
  readonly rolesUpdated: "roles_updated";
13
+ readonly generationStarted: "generation_started";
14
+ readonly generationFinished: "generation_finished";
13
15
  };
14
16
  export type EventType = (typeof EVENT_TYPES)[keyof typeof EVENT_TYPES];
17
+ /**
18
+ * Long-running async work originated by a plugin (MulmoScript etc.)
19
+ * that continues past the initial HTTP response. The server publishes
20
+ * a `generationStarted` event when the work begins and a
21
+ * `generationFinished` event when it completes (or fails). Clients
22
+ * track the in-flight set in `Session.pendingGenerations` so the UI
23
+ * can keep a "busy" indicator lit across view navigation.
24
+ */
25
+ export declare const GENERATION_KINDS: {
26
+ readonly beatImage: "beatImage";
27
+ readonly characterImage: "characterImage";
28
+ readonly beatAudio: "beatAudio";
29
+ readonly movie: "movie";
30
+ };
31
+ export type GenerationKind = (typeof GENERATION_KINDS)[keyof typeof GENERATION_KINDS];
32
+ export interface GenerationEvent {
33
+ type: "generation_started" | "generation_finished";
34
+ kind: GenerationKind;
35
+ /** MulmoScript file path — identifies the script the generation belongs to. */
36
+ filePath: string;
37
+ /** beatIndex (as string) for beat*, character key for characterImage, "" for movie. */
38
+ key: string;
39
+ /** Only set on generation_finished when the work failed. */
40
+ error?: string;
41
+ }
42
+ /**
43
+ * Decomposed view of a pending generation, stored as the *value* of
44
+ * `pendingGenerations[mapKey]`. Consumers read these fields directly
45
+ * rather than splitting the composite map key — filePath and user-
46
+ * defined character keys can contain arbitrary characters, so
47
+ * positional string parsing is unsafe.
48
+ */
49
+ export interface PendingGeneration {
50
+ kind: GenerationKind;
51
+ filePath: string;
52
+ key: string;
53
+ }
54
+ /**
55
+ * Stable map-key for a generation: the triple (kind, filePath, key).
56
+ * Separator is U+001F (UNIT SEPARATOR), a non-printable ASCII control
57
+ * character that cannot appear in filePaths or user-entered keys —
58
+ * this guarantees `generationKey(a) === generationKey(b)` iff a≡b,
59
+ * unlike a human-visible delimiter that could collide.
60
+ *
61
+ * The returned string is used only as a map identity. Do NOT split it
62
+ * to recover the fields — store the decomposed `PendingGeneration`
63
+ * object as the map value instead.
64
+ */
65
+ export declare function generationKey(kind: GenerationKind, filePath: string, key: string): string;
package/dist/events.js CHANGED
@@ -15,4 +15,34 @@ export const EVENT_TYPES = {
15
15
  sessionFinished: "session_finished",
16
16
  sessionMeta: "session_meta",
17
17
  rolesUpdated: "roles_updated",
18
+ generationStarted: "generation_started",
19
+ generationFinished: "generation_finished",
18
20
  };
21
+ /**
22
+ * Long-running async work originated by a plugin (MulmoScript etc.)
23
+ * that continues past the initial HTTP response. The server publishes
24
+ * a `generationStarted` event when the work begins and a
25
+ * `generationFinished` event when it completes (or fails). Clients
26
+ * track the in-flight set in `Session.pendingGenerations` so the UI
27
+ * can keep a "busy" indicator lit across view navigation.
28
+ */
29
+ export const GENERATION_KINDS = {
30
+ beatImage: "beatImage",
31
+ characterImage: "characterImage",
32
+ beatAudio: "beatAudio",
33
+ movie: "movie",
34
+ };
35
+ /**
36
+ * Stable map-key for a generation: the triple (kind, filePath, key).
37
+ * Separator is U+001F (UNIT SEPARATOR), a non-printable ASCII control
38
+ * character that cannot appear in filePaths or user-entered keys —
39
+ * this guarantees `generationKey(a) === generationKey(b)` iff a≡b,
40
+ * unlike a human-visible delimiter that could collide.
41
+ *
42
+ * The returned string is used only as a map identity. Do NOT split it
43
+ * to recover the fields — store the decomposed `PendingGeneration`
44
+ * object as the map value instead.
45
+ */
46
+ export function generationKey(kind, filePath, key) {
47
+ return `${kind}\u001f${filePath}\u001f${key}`;
48
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { EVENT_TYPES, type EventType } from "./events.js";
2
- export { CHAT_SOCKET_PATH, CHAT_SOCKET_EVENTS, type ChatSocketEvent, } from "./socket.js";
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, 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/index.js CHANGED
@@ -6,6 +6,6 @@
6
6
  // - External bridges (CLI, Telegram, future platforms)
7
7
  //
8
8
  // No runtime dependencies. Types + const-only.
9
- export { EVENT_TYPES } from "./events.js";
10
- export { CHAT_SOCKET_PATH, CHAT_SOCKET_EVENTS, } from "./socket.js";
9
+ export { EVENT_TYPES, GENERATION_KINDS, generationKey } from "./events.js";
10
+ export { CHAT_SOCKET_PATH, CHAT_SOCKET_EVENTS } from "./socket.js";
11
11
  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/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.2",
3
+ "version": "0.1.4",
4
4
  "description": "Shared types and constants for the MulmoBridge protocol",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",