@neta-art/cohub-protocol 1.2.0 → 1.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.
@@ -48,20 +48,42 @@ export interface GatewayInboundEvent {
48
48
  meta?: Record<string, unknown> | null;
49
49
  }
50
50
  export interface GatewaySessionOutputBase {
51
- type: "session.turn.progress" | "session.turn.final" | "session.turn.error" | "session.message.persisted";
51
+ type: "session.turn.patch" | "session.turn.error" | "session.message.persisted";
52
52
  spaceId: string;
53
53
  sessionId: string;
54
54
  }
55
- export interface GatewaySessionTurnProgressOutput extends GatewaySessionOutputBase {
56
- type: "session.turn.progress";
55
+ export type GatewaySessionPatchOperation = {
56
+ o: "append";
57
+ p: string;
58
+ v: unknown;
59
+ } | {
60
+ o: "replace";
61
+ p: string;
62
+ v: unknown;
63
+ } | {
64
+ o: "add";
65
+ p: string;
66
+ v: unknown;
67
+ } | {
68
+ o: "merge";
69
+ p: string;
70
+ v: Record<string, unknown>;
71
+ } | {
72
+ o: "remove";
73
+ p: string;
74
+ } | {
75
+ v: unknown;
76
+ o?: undefined;
77
+ p?: undefined;
78
+ };
79
+ export interface GatewaySessionTurnPatchOutput extends GatewaySessionOutputBase {
80
+ type: "session.turn.patch";
81
+ turnId: string | null;
82
+ messageId: string | null;
57
83
  anchorUserMessageId: string | null;
58
- content: ContentBlock[];
59
- }
60
- export interface GatewaySessionTurnFinalOutput extends GatewaySessionOutputBase {
61
- type: "session.turn.final";
62
- sessionMessageId: string | null;
63
- anchorUserMessageId: string | null;
64
- content: ContentBlock[];
84
+ seq: number;
85
+ baseSeq: number;
86
+ ops: GatewaySessionPatchOperation[];
65
87
  }
66
88
  export interface GatewaySessionTurnErrorOutput extends GatewaySessionOutputBase {
67
89
  type: "session.turn.error";
@@ -72,7 +94,7 @@ export interface GatewaySessionMessagePersistedOutput extends GatewaySessionOutp
72
94
  type: "session.message.persisted";
73
95
  message: MessageRecord;
74
96
  }
75
- export type GatewaySessionOutput = GatewaySessionTurnProgressOutput | GatewaySessionTurnFinalOutput | GatewaySessionTurnErrorOutput | GatewaySessionMessagePersistedOutput;
97
+ export type GatewaySessionOutput = GatewaySessionTurnPatchOutput | GatewaySessionTurnErrorOutput | GatewaySessionMessagePersistedOutput;
76
98
  export interface GatewayOutboundCommand {
77
99
  commandId: string;
78
100
  timestamp: number;
@@ -0,0 +1,136 @@
1
+ export type ChannelProvider = "web" | "websocket" | "discord" | "feishu" | "telegram" | "slack";
2
+ export declare function buildSessionSourceChannel(event: GatewayInboundEvent): string;
3
+ export interface DiscordChannelConfig {
4
+ inbound?: {
5
+ requireMentionInGuild?: boolean;
6
+ };
7
+ outbound?: {
8
+ showThinking?: boolean;
9
+ showToolCalls?: boolean;
10
+ };
11
+ }
12
+ export type ChannelConfig = DiscordChannelConfig | FeishuChannelConfig | Record<string, unknown>;
13
+ export interface FeishuChannelConfig {
14
+ brand?: "feishu" | "lark";
15
+ inbound?: {
16
+ requireMentionInGroup?: boolean;
17
+ };
18
+ outbound?: {
19
+ renderMode?: "card" | "post";
20
+ showThinking?: boolean;
21
+ showToolCalls?: boolean;
22
+ };
23
+ }
24
+ export interface GatewayInboundEvent {
25
+ eventId: string;
26
+ timestamp: number;
27
+ eventType?: "message_create" | "conversation_create";
28
+ channelId: string;
29
+ provider: ChannelProvider;
30
+ externalChatId: string;
31
+ externalMessageId: string;
32
+ bindingKey?: string;
33
+ conversation: {
34
+ id: string;
35
+ parentId?: string | null;
36
+ meta?: Record<string, unknown> | null;
37
+ };
38
+ message?: {
39
+ parentMessageId?: string | null;
40
+ meta?: Record<string, unknown> | null;
41
+ };
42
+ sender: {
43
+ id: string;
44
+ name?: string;
45
+ };
46
+ content: import("./session-ingestion.js").ContentBlock[];
47
+ meta?: Record<string, unknown> | null;
48
+ }
49
+ export interface GatewaySessionOutputBase {
50
+ type: "session.turn.progress" | "session.turn.final" | "session.turn.error" | "session.message.persisted";
51
+ spaceId: string;
52
+ sessionId: string;
53
+ }
54
+ export interface GatewaySessionTurnProgressOutput extends GatewaySessionOutputBase {
55
+ type: "session.turn.progress";
56
+ anchorUserMessageId: string | null;
57
+ content: import("./session-ingestion.js").ContentBlock[];
58
+ }
59
+ export interface GatewaySessionTurnFinalOutput extends GatewaySessionOutputBase {
60
+ type: "session.turn.final";
61
+ sessionMessageId: string | null;
62
+ anchorUserMessageId: string | null;
63
+ content: import("./session-ingestion.js").ContentBlock[];
64
+ }
65
+ export interface GatewaySessionTurnErrorOutput extends GatewaySessionOutputBase {
66
+ type: "session.turn.error";
67
+ anchorUserMessageId: string | null;
68
+ error: string;
69
+ }
70
+ export interface GatewaySessionMessagePersistedOutput extends GatewaySessionOutputBase {
71
+ type: "session.message.persisted";
72
+ message: import("./session-ingestion.js").MessageRecord;
73
+ }
74
+ export type GatewaySessionOutput = GatewaySessionTurnProgressOutput | GatewaySessionTurnFinalOutput | GatewaySessionTurnErrorOutput | GatewaySessionMessagePersistedOutput;
75
+ export interface DiscordDeliveryPlan {
76
+ adapter: "discord";
77
+ mode: "send" | "upsert";
78
+ primaryText: string;
79
+ continuationChunks: string[];
80
+ files: string[];
81
+ replyToExternalMessageId?: string;
82
+ turnAnchorMessageId?: string | null;
83
+ preferredEditExternalMessageId?: string | null;
84
+ }
85
+ export interface FeishuDeliveryPlan {
86
+ adapter: "feishu";
87
+ mode: "create_or_update";
88
+ renderMode: "card" | "post";
89
+ msgType: "interactive" | "post";
90
+ content: string;
91
+ imageKeys: string[];
92
+ replyToExternalMessageId?: string;
93
+ turnAnchorMessageId?: string | null;
94
+ preferredEditExternalMessageId?: string | null;
95
+ }
96
+ export type GatewayDeliveryPlan = DiscordDeliveryPlan | FeishuDeliveryPlan;
97
+ export interface GatewayOutboundCommand {
98
+ commandId: string;
99
+ timestamp: number;
100
+ channelId: string;
101
+ provider: ChannelProvider;
102
+ externalChatId: string;
103
+ content: import("./session-ingestion.js").ContentBlock[];
104
+ replyToExternalMessageId?: string;
105
+ spaceId?: string;
106
+ spaceSessionId?: string;
107
+ sessionMessageId?: string;
108
+ deliveryPlan?: GatewayDeliveryPlan | null;
109
+ meta?: (Record<string, unknown> & {
110
+ sessionOutput?: GatewaySessionOutput | null;
111
+ }) | null;
112
+ }
113
+ export interface GatewayControlCommand {
114
+ action: "connect" | "disconnect" | "reload";
115
+ configs: {
116
+ channelId: string;
117
+ provider: ChannelProvider;
118
+ credentials: Record<string, unknown>;
119
+ }[];
120
+ }
121
+ export type GatewayLogDirection = "inbound" | "outbound";
122
+ export type GatewayLogStatus = "pending" | "success" | "failed";
123
+ export interface GatewayLogEvent {
124
+ logId: string;
125
+ timestamp: number;
126
+ direction: GatewayLogDirection;
127
+ provider: ChannelProvider;
128
+ channelId: string;
129
+ externalChatId: string;
130
+ externalMessageId?: string;
131
+ rawPayload: Record<string, unknown>;
132
+ normalizedPayload?: Record<string, unknown>;
133
+ status: GatewayLogStatus;
134
+ errorMessage?: string;
135
+ correlationId?: string;
136
+ }
@@ -0,0 +1,48 @@
1
+ export function buildSessionSourceChannel(event) {
2
+ const provider = event.provider;
3
+ const meta = (event.conversation?.meta ?? event.meta ?? {});
4
+ switch (provider) {
5
+ case "discord":
6
+ return buildDiscordSourceChannel(event, meta);
7
+ case "feishu":
8
+ return buildFeishuSourceChannel(event, meta);
9
+ case "web":
10
+ return "web";
11
+ default:
12
+ return `${provider}:${event.conversation?.id?.trim() || event.externalChatId}`;
13
+ }
14
+ }
15
+ function buildDiscordSourceChannel(event, meta) {
16
+ const isDm = meta.isDm === true;
17
+ const guildName = typeof meta.guildName === "string" ? meta.guildName : null;
18
+ const channelName = typeof meta.channelName === "string" ? meta.channelName : null;
19
+ const parentChannelName = typeof meta.parentChannelName === "string" ? meta.parentChannelName : null;
20
+ const threadName = typeof meta.threadName === "string" ? meta.threadName : null;
21
+ const senderName = event.sender?.name ?? null;
22
+ if (isDm) {
23
+ return `discord:dm:${senderName ?? event.sender.id}`;
24
+ }
25
+ if (threadName && parentChannelName && guildName) {
26
+ return `discord:${guildName}:#${parentChannelName}>${threadName}`;
27
+ }
28
+ if (channelName && guildName) {
29
+ return `discord:${guildName}:#${channelName}`;
30
+ }
31
+ if (guildName) {
32
+ return `discord:${guildName}`;
33
+ }
34
+ return `discord:${event.conversation?.id?.trim() || event.externalChatId}`;
35
+ }
36
+ function buildFeishuSourceChannel(event, meta) {
37
+ const chatType = meta.chatType;
38
+ const chatName = typeof meta.chatName === "string" ? meta.chatName : null;
39
+ const senderName = event.sender?.name ?? null;
40
+ const isDm = chatType === "p2p";
41
+ if (isDm) {
42
+ return `feishu:dm:${senderName ?? event.sender.id}`;
43
+ }
44
+ if (chatName) {
45
+ return `feishu:group:${chatName}`;
46
+ }
47
+ return `feishu:${event.conversation?.id?.trim() || event.externalChatId}`;
48
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./core/content.js";
2
2
  export * from "./core/usage.js";
3
3
  export * from "./model/session.js";
4
+ export * from "./model/turn.js";
4
5
  export * from "./realtime/stream.js";
5
6
  export * from "./realtime/websocket.js";
6
7
  export * from "./gateway/index.js";
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./core/content.js";
2
2
  export * from "./core/usage.js";
3
3
  export * from "./model/session.js";
4
+ export * from "./model/turn.js";
4
5
  export * from "./realtime/stream.js";
5
6
  export * from "./realtime/websocket.js";
6
7
  export * from "./gateway/index.js";
@@ -1,5 +1,6 @@
1
1
  import type { ContentBlock } from "../core/content.js";
2
2
  import type { Usage } from "../core/usage.js";
3
+ export type { MessageToolCallsFile, SessionTurnIntent, SessionTurnIntermediateIndex, SessionTurnIntermediateSummary, SessionTurnRecord, SessionTurnStatus, SessionTurnSummary, StoredIntermediateMessage, StoredIntermediateMessageToolCallSummary, StoredToolCall, TurnIntermediateMessagesFile, } from "./turn.js";
3
4
  export type SessionPromptInput = {
4
5
  spaceId: string;
5
6
  sessionId: string;
@@ -9,9 +10,10 @@ export type SessionPromptInput = {
9
10
  };
10
11
  meta?: {
11
12
  source?: string;
12
- intent?: "auto" | "continue" | "new_session" | "fork";
13
+ intent?: "auto" | "continue" | "new_session" | "fork" | "steer" | "followup";
13
14
  model?: string;
14
15
  provider?: string;
16
+ turnId?: string;
15
17
  } | null;
16
18
  };
17
19
  export type RegisterSessionInput = {
@@ -0,0 +1,95 @@
1
+ import type { ContentBlock } from "../core/content.js";
2
+ import type { Usage } from "../core/usage.js";
3
+ export type SessionTurnStatus = "running" | "completed" | "failed" | "interrupted";
4
+ export type SessionTurnIntent = "steer" | "followup";
5
+ export type SessionTurnSummary = {
6
+ text?: string | null;
7
+ finishReason?: "completed" | "failed" | "interrupted";
8
+ interruptedByTurnId?: string | null;
9
+ };
10
+ export type SessionTurnIntermediateIndex = {
11
+ version: 1;
12
+ messagesObjectKey: string | null;
13
+ messagesSizeBytes?: number | null;
14
+ toolCallsBaseObjectKey?: string | null;
15
+ };
16
+ export type SessionTurnIntermediateSummary = {
17
+ messageCount: number;
18
+ toolCallCount: number;
19
+ usage?: Usage | null;
20
+ lastMessageText?: string | null;
21
+ hasError?: boolean;
22
+ };
23
+ export type StoredIntermediateMessageToolCallSummary = {
24
+ id: string;
25
+ name: string;
26
+ status: "running" | "done" | "failed";
27
+ input: Record<string, unknown>;
28
+ };
29
+ export type StoredIntermediateMessage = {
30
+ id: string;
31
+ sessionId: string;
32
+ role: "user" | "assistant" | "system";
33
+ content: ContentBlock[];
34
+ text: string | null;
35
+ provider: string | null;
36
+ model: string | null;
37
+ stopReason: string | null;
38
+ errorMessage: string | null;
39
+ usage: Usage | null;
40
+ toolCalls: StoredIntermediateMessageToolCallSummary[];
41
+ toolCallsObjectKey: string | null;
42
+ meta: Record<string, unknown> | null;
43
+ createdAt: string;
44
+ };
45
+ export type StoredToolCall = {
46
+ id: string;
47
+ name: string;
48
+ input: Record<string, unknown>;
49
+ result: {
50
+ content: string | ContentBlock[] | null;
51
+ isError: boolean;
52
+ } | null;
53
+ meta: Record<string, unknown> | null;
54
+ };
55
+ export type MessageToolCallsFile = {
56
+ version: 1;
57
+ spaceId: string;
58
+ sessionId: string;
59
+ turnId: string;
60
+ messageId: string;
61
+ toolCalls: StoredToolCall[];
62
+ };
63
+ export type TurnIntermediateMessagesFile = {
64
+ version: 1;
65
+ spaceId: string;
66
+ sessionId: string;
67
+ turnId: string;
68
+ summary: SessionTurnIntermediateSummary;
69
+ messages: StoredIntermediateMessage[];
70
+ };
71
+ export type SessionTurnRecord = {
72
+ id: string;
73
+ sessionId: string;
74
+ userUuid: string | null;
75
+ sequence: number;
76
+ status: SessionTurnStatus;
77
+ intent: SessionTurnIntent;
78
+ userContent: ContentBlock[];
79
+ userText: string | null;
80
+ assistantContent: ContentBlock[] | null;
81
+ assistantText: string | null;
82
+ provider: string | null;
83
+ model: string | null;
84
+ stopReason: string | null;
85
+ errorMessage: string | null;
86
+ usage: Usage | null;
87
+ summary: SessionTurnSummary | null;
88
+ intermediateIndex: SessionTurnIntermediateIndex | null;
89
+ intermediateSummary: SessionTurnIntermediateSummary | null;
90
+ meta: Record<string, unknown> | null;
91
+ startedAt: string | null;
92
+ completedAt: string | null;
93
+ createdAt: string;
94
+ updatedAt: string;
95
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Permission level for space / session resources.
3
+ *
4
+ * - `read` — anyone can read (including anonymous users)
5
+ * - `write` — anyone can read and write
6
+ * - `private` — explicitly deny access (no fallback to parent)
7
+ */
8
+ export type ResourcePermissionLevel = "read" | "write" | "private";
@@ -0,0 +1 @@
1
+ export {};
@@ -3,6 +3,9 @@ export type SessionStreamEvent = {
3
3
  type: "stream_update";
4
4
  spaceId: string;
5
5
  sessionId: string;
6
+ turnId?: string | null;
7
+ seq: number;
8
+ baseSeq: number;
6
9
  content: ContentBlock[];
7
10
  sourceMessageId: string | null;
8
11
  timestamp: number;
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import type { ContentBlock } from "../core/content.js";
3
3
  import type { MessageRecord } from "../model/session.js";
4
4
  import type { SpaceFsChangedPayload } from "../fs/index.js";
5
+ export declare const WS_COMPACT_STREAM_CAPABILITY = "session.compact_stream.v1";
5
6
  export declare const contentBlockSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
6
7
  type: z.ZodLiteral<"text">;
7
8
  text: z.ZodString;
@@ -50,6 +51,7 @@ export declare const wsClientEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
50
51
  requestId: z.ZodOptional<z.ZodString>;
51
52
  payload: z.ZodObject<{
52
53
  token: z.ZodString;
54
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
53
55
  }, z.core.$strip>;
54
56
  }, z.core.$strip>, z.ZodObject<{
55
57
  type: z.ZodLiteral<"session.message.create">;
@@ -143,11 +145,33 @@ export declare const channelEnvelopeSchema: z.ZodObject<{
143
145
  sessionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
144
146
  payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
145
147
  }, z.core.$strip>;
148
+ export declare const realtimeCompactFrameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
149
+ t: z.ZodLiteral<"d">;
150
+ sid: z.ZodString;
151
+ s: z.ZodNumber;
152
+ b: z.ZodNumber;
153
+ v: z.ZodUnknown;
154
+ }, z.core.$strip>, z.ZodObject<{
155
+ t: z.ZodLiteral<"p">;
156
+ sid: z.ZodString;
157
+ s: z.ZodNumber;
158
+ b: z.ZodNumber;
159
+ o: z.ZodEnum<{
160
+ append: "append";
161
+ replace: "replace";
162
+ add: "add";
163
+ merge: "merge";
164
+ remove: "remove";
165
+ }>;
166
+ p: z.ZodString;
167
+ v: z.ZodOptional<z.ZodUnknown>;
168
+ }, z.core.$strip>], "t">;
146
169
  export type WsClientEvent = {
147
170
  type: "auth";
148
171
  requestId?: string;
149
172
  payload: {
150
173
  token: string;
174
+ capabilities?: string[];
151
175
  };
152
176
  } | {
153
177
  type: "session.message.create";
@@ -173,6 +197,7 @@ export type WsClientEvent = {
173
197
  };
174
198
  export type RealtimeEnvelope = z.output<typeof realtimeEnvelopeSchema>;
175
199
  export type ChannelEnvelope = RealtimeEnvelope;
200
+ export type RealtimeCompactFrame = z.output<typeof realtimeCompactFrameSchema>;
176
201
  export type RealtimeEnvelopeBase = RealtimeEnvelope;
177
202
  export type RealtimeDomain = RealtimeEnvelopeBase["domain"];
178
203
  export type SystemReadyEvent = {
@@ -272,18 +297,45 @@ export type SessionTurnProgressEvent = {
272
297
  content: ContentBlock[];
273
298
  };
274
299
  };
275
- export type SessionTurnFinalEvent = {
300
+ export type RealtimePatchOperation = {
301
+ o: "append";
302
+ p: string;
303
+ v: unknown;
304
+ } | {
305
+ o: "replace";
306
+ p: string;
307
+ v: unknown;
308
+ } | {
309
+ o: "add";
310
+ p: string;
311
+ v: unknown;
312
+ } | {
313
+ o: "merge";
314
+ p: string;
315
+ v: Record<string, unknown>;
316
+ } | {
317
+ o: "remove";
318
+ p: string;
319
+ } | {
320
+ v: unknown;
321
+ o?: undefined;
322
+ p?: undefined;
323
+ };
324
+ export type SessionTurnPatchEvent = {
276
325
  id: string;
277
326
  timestamp: number;
278
327
  domain: "session";
279
- type: "session.turn.final";
328
+ type: "session.turn.patch";
280
329
  requestId?: string | null;
281
330
  spaceId: string;
282
331
  sessionId: string;
283
332
  payload: {
284
- sessionMessageId: string | null;
333
+ turnId: string | null;
334
+ messageId: string | null;
285
335
  anchorUserMessageId: string | null;
286
- content: ContentBlock[];
336
+ seq: number;
337
+ baseSeq: number;
338
+ ops: RealtimePatchOperation[];
287
339
  };
288
340
  };
289
341
  export type SessionTurnErrorEvent = {
@@ -299,6 +351,7 @@ export type SessionTurnErrorEvent = {
299
351
  error: string;
300
352
  };
301
353
  };
354
+ export type RealtimeMessageRecord = Pick<MessageRecord, "id" | "sessionId" | "role" | "content" | "text" | "sequence" | "provider" | "model" | "stopReason" | "errorMessage" | "usage" | "meta" | "createdAt">;
302
355
  export type SessionMessagePersistedEvent = {
303
356
  id: string;
304
357
  timestamp: number;
@@ -308,7 +361,7 @@ export type SessionMessagePersistedEvent = {
308
361
  spaceId: string;
309
362
  sessionId: string;
310
363
  payload: {
311
- message: MessageRecord;
364
+ message: RealtimeMessageRecord;
312
365
  };
313
366
  };
314
367
  export type SpaceFsChangedEvent = {
@@ -321,6 +374,6 @@ export type SpaceFsChangedEvent = {
321
374
  sessionId?: string | null;
322
375
  payload: SpaceFsChangedPayload;
323
376
  };
324
- export type RealtimeServerEvent = SystemReadyEvent | SystemAuthOkEvent | SystemRequestErrorEvent | SystemPongEvent | SystemAckOkEvent | SessionRequestAcceptedEvent | SessionRequestErrorEvent | SessionTurnProgressEvent | SessionTurnFinalEvent | SessionTurnErrorEvent | SessionMessagePersistedEvent | SpaceFsChangedEvent;
377
+ export type RealtimeServerEvent = SystemReadyEvent | SystemAuthOkEvent | SystemRequestErrorEvent | SystemPongEvent | SystemAckOkEvent | SessionRequestAcceptedEvent | SessionRequestErrorEvent | SessionTurnProgressEvent | SessionTurnPatchEvent | SessionTurnErrorEvent | SessionMessagePersistedEvent | SpaceFsChangedEvent;
325
378
  export type WsServerEnvelope = RealtimeEnvelope;
326
379
  export type ChannelServerEnvelope = ChannelEnvelope;
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  const contentBlockMetaSchema = z.record(z.string(), z.unknown());
3
+ export const WS_COMPACT_STREAM_CAPABILITY = "session.compact_stream.v1";
3
4
  export const contentBlockSchema = z.discriminatedUnion("type", [
4
5
  z.object({
5
6
  type: z.literal("text"),
@@ -45,7 +46,10 @@ export const wsClientEventSchema = z.discriminatedUnion("type", [
45
46
  z.object({
46
47
  type: z.literal("auth"),
47
48
  requestId: z.string().optional(),
48
- payload: z.object({ token: z.string().min(1) }),
49
+ payload: z.object({
50
+ token: z.string().min(1),
51
+ capabilities: z.array(z.string().min(1)).optional(),
52
+ }),
49
53
  }),
50
54
  z.object({
51
55
  type: z.literal("session.message.create"),
@@ -83,3 +87,21 @@ export const realtimeEnvelopeSchema = z.object({
83
87
  payload: z.record(z.string(), z.unknown()),
84
88
  });
85
89
  export const channelEnvelopeSchema = realtimeEnvelopeSchema;
90
+ export const realtimeCompactFrameSchema = z.discriminatedUnion("t", [
91
+ z.object({
92
+ t: z.literal("d"),
93
+ sid: z.string().min(1),
94
+ s: z.number().int().nonnegative(),
95
+ b: z.number().int().nonnegative(),
96
+ v: z.unknown(),
97
+ }),
98
+ z.object({
99
+ t: z.literal("p"),
100
+ sid: z.string().min(1),
101
+ s: z.number().int().nonnegative(),
102
+ b: z.number().int().nonnegative(),
103
+ o: z.enum(["append", "replace", "add", "merge", "remove"]),
104
+ p: z.string().min(1),
105
+ v: z.unknown().optional(),
106
+ }),
107
+ ]);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export {};
2
+ // Responses API has been removed.
3
+ // Sessions now work via simple POST /sessions/:id/messages.
4
+ // Frontend live updates are delivered via Gateway WebSocket.
@@ -0,0 +1,158 @@
1
+ export type ContentBlockMeta = Record<string, unknown>;
2
+ export type ContentBlock = {
3
+ type: "text";
4
+ text: string;
5
+ _meta?: ContentBlockMeta;
6
+ } | {
7
+ type: "thinking";
8
+ thinking: string;
9
+ signature?: string;
10
+ _meta?: ContentBlockMeta;
11
+ } | {
12
+ type: "image";
13
+ source: {
14
+ type: "url";
15
+ url: string;
16
+ } | {
17
+ type: "base64";
18
+ media_type: string;
19
+ data: string;
20
+ };
21
+ _meta?: ContentBlockMeta;
22
+ } | {
23
+ type: "tool_use";
24
+ id: string;
25
+ name: string;
26
+ input: Record<string, unknown>;
27
+ _meta?: ContentBlockMeta;
28
+ } | {
29
+ type: "tool_result";
30
+ tool_use_id: string;
31
+ content: string | ContentBlock[];
32
+ is_error?: boolean;
33
+ _meta?: ContentBlockMeta;
34
+ } | {
35
+ type: "system_note";
36
+ note_type: "session_created" | "forked" | "compacted" | "info";
37
+ text: string;
38
+ _meta?: ContentBlockMeta;
39
+ };
40
+ export type SessionPromptInput = {
41
+ spaceId: string;
42
+ sessionId: string;
43
+ userMessageId?: string | null;
44
+ message: {
45
+ content: ContentBlock[];
46
+ };
47
+ meta?: {
48
+ source?: string;
49
+ intent?: "auto" | "continue" | "new_session" | "fork";
50
+ model?: string;
51
+ provider?: string;
52
+ } | null;
53
+ };
54
+ export type RegisterSessionInput = {
55
+ spaceId: string;
56
+ sessionId: string;
57
+ title?: string | null;
58
+ source?: string | null;
59
+ externalSessionId?: string | null;
60
+ meta?: Record<string, unknown> | null;
61
+ };
62
+ export type PersistMessageInput = {
63
+ spaceId: string;
64
+ sessionId: string;
65
+ previousMessageId?: string | null;
66
+ anchorUserMessageId?: string | null;
67
+ idempotencyKey: string;
68
+ message: {
69
+ role?: "user" | "assistant" | "system";
70
+ externalMessageId?: string | null;
71
+ protocolMessageId?: string | null;
72
+ content: ContentBlock[];
73
+ text?: string | null;
74
+ provider?: string | null;
75
+ model?: string | null;
76
+ stopReason?: string | null;
77
+ errorMessage?: string | null;
78
+ meta?: Record<string, unknown> | null;
79
+ usage?: {
80
+ input?: number;
81
+ output?: number;
82
+ costTotal?: number;
83
+ } | null;
84
+ };
85
+ };
86
+ export type UpdateSessionInfoInput = {
87
+ spaceId: string;
88
+ sessionId: string;
89
+ title?: string | null;
90
+ updatedAt?: string | null;
91
+ meta?: Record<string, unknown> | null;
92
+ };
93
+ export type SessionStreamEvent = {
94
+ type: "stream_update";
95
+ spaceId: string;
96
+ sessionId: string;
97
+ /** `content` always contains delta blocks to be merged into the current streaming state. */
98
+ content: ContentBlock[];
99
+ sourceMessageId: string | null;
100
+ timestamp: number;
101
+ turnEnd?: boolean;
102
+ anchorUserMessageId?: string | null;
103
+ };
104
+ export type SessionStreamError = {
105
+ type: "error";
106
+ spaceId: string;
107
+ sessionId: string | null;
108
+ error: string;
109
+ };
110
+ export type SessionBindingRecord = {
111
+ id: string;
112
+ spaceId: string;
113
+ spaceSessionId: string;
114
+ spaceChannelId: string;
115
+ provider: string;
116
+ bindingKey: string;
117
+ externalChatId: string;
118
+ status: string | null;
119
+ meta: Record<string, unknown> | null;
120
+ createdAt: string;
121
+ updatedAt: string;
122
+ lastMessageAt: string | null;
123
+ };
124
+ export type SessionRecord = {
125
+ id: string;
126
+ spaceId: string;
127
+ title: string | null;
128
+ source: string | null;
129
+ status: string | null;
130
+ externalSessionId: string | null;
131
+ meta: Record<string, unknown> | null;
132
+ parentSessionId: string | null;
133
+ forkedFromMessageId: string | null;
134
+ lineageRootSessionId: string | null;
135
+ forkDepth: number;
136
+ latestMessageText: string | null;
137
+ lastMessageAt: string | null;
138
+ lastMessageId: string | null;
139
+ createdAt: string;
140
+ updatedAt: string;
141
+ };
142
+ export type MessageRecord = {
143
+ id: string;
144
+ sessionId: string;
145
+ role: "user" | "assistant" | "system";
146
+ content: ContentBlock[];
147
+ text: string | null;
148
+ sequence: number;
149
+ provider: string | null;
150
+ model: string | null;
151
+ stopReason: string | null;
152
+ errorMessage: string | null;
153
+ usageInput: number | null;
154
+ usageOutput: number | null;
155
+ costTotal: string | null;
156
+ meta: Record<string, unknown> | null;
157
+ createdAt: string;
158
+ };
@@ -0,0 +1,2 @@
1
+ // ─── Content Block — Anthropic-style, single source of truth ───
2
+ export {};
@@ -0,0 +1,33 @@
1
+ export type SpaceFsEntry = {
2
+ name: string;
3
+ path: string;
4
+ type: "file" | "dir" | "symlink";
5
+ size: number;
6
+ mimeType: string | null;
7
+ mtimeMs: number;
8
+ };
9
+ export type SpaceFsTreeResponse = {
10
+ path: string;
11
+ entries: SpaceFsEntry[];
12
+ };
13
+ export type SpaceFsFileKind = "text" | "binary";
14
+ export type SpaceFsEncoding = "utf-8" | "base64";
15
+ export type SpaceFsFileResponse = {
16
+ path: string;
17
+ name: string;
18
+ size: number;
19
+ mimeType: string | null;
20
+ mtimeMs: number;
21
+ kind: SpaceFsFileKind;
22
+ encoding: SpaceFsEncoding;
23
+ content: string;
24
+ };
25
+ export type SpaceFsWriteFileInput = {
26
+ path: string;
27
+ content: string;
28
+ encoding: SpaceFsEncoding;
29
+ };
30
+ export type SpaceFsMoveInput = {
31
+ fromPath: string;
32
+ toPath: string;
33
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Space sandbox lifecycle status.
3
+ *
4
+ * Internal infrastructure state only.
5
+ * Not intended as a primary user-facing concept.
6
+ */
7
+ export type SpaceSandboxStatus = "pending" | "provisioning" | "ready" | "stopped" | "error" | "terminated";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Task system protocol definitions.
3
+ * Shared between API (scheduler) and Worker (executor).
4
+ */
5
+ /**
6
+ * Task type identifier.
7
+ * Open-ended — add new types as needed.
8
+ */
9
+ export type TaskType = string;
10
+ /**
11
+ * Universal task payload carried by every BullMQ job.
12
+ * Fields like spaceId / sessionId are optional
13
+ * so tasks can be scoped or global.
14
+ */
15
+ export interface TaskPayload {
16
+ type: TaskType;
17
+ /** Optional: which space this task relates to */
18
+ spaceId?: string;
19
+ /** Optional: which session this task relates to */
20
+ sessionId?: string;
21
+ /** Optional: the user who owns / triggered this task */
22
+ userId?: string;
23
+ /** Optional: cron job that spawned this execution (set by API on enqueue) */
24
+ cronJobId?: string;
25
+ /** Task-specific parameters */
26
+ data?: Record<string, unknown>;
27
+ }
28
+ /**
29
+ * Task run status in the database.
30
+ *
31
+ * Flow:
32
+ * pending (API-enqueued only)
33
+ * → running (worker picked up)
34
+ * → completed | failed
35
+ */
36
+ export type TaskRunStatus = "pending" | "running" | "completed" | "failed";
37
+ /**
38
+ * Cron schedule configuration passed from the client.
39
+ */
40
+ export interface TaskScheduleConfig {
41
+ /** Cron expression, e.g. "0 10 * * *" */
42
+ pattern: string;
43
+ /** IANA timezone, defaults to "Asia/Shanghai" */
44
+ timezone?: string;
45
+ }
package/dist/tasks.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Task system protocol definitions.
3
+ * Shared between API (scheduler) and Worker (executor).
4
+ */
5
+ export {};
@@ -0,0 +1,299 @@
1
+ import { z } from "zod";
2
+ import type { ContentBlock, MessageRecord } from "./session-ingestion.js";
3
+ export declare const contentBlockSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4
+ type: z.ZodLiteral<"text">;
5
+ text: z.ZodString;
6
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
7
+ }, z.core.$strip>, z.ZodObject<{
8
+ type: z.ZodLiteral<"thinking">;
9
+ thinking: z.ZodString;
10
+ signature: z.ZodOptional<z.ZodString>;
11
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
12
+ }, z.core.$strip>, z.ZodObject<{
13
+ type: z.ZodLiteral<"image">;
14
+ source: z.ZodUnion<readonly [z.ZodObject<{
15
+ type: z.ZodLiteral<"url">;
16
+ url: z.ZodString;
17
+ }, z.core.$strip>, z.ZodObject<{
18
+ type: z.ZodLiteral<"base64">;
19
+ media_type: z.ZodString;
20
+ data: z.ZodString;
21
+ }, z.core.$strip>]>;
22
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
23
+ }, z.core.$strip>, z.ZodObject<{
24
+ type: z.ZodLiteral<"tool_use">;
25
+ id: z.ZodString;
26
+ name: z.ZodString;
27
+ input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
28
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
29
+ }, z.core.$strip>, z.ZodObject<{
30
+ type: z.ZodLiteral<"tool_result">;
31
+ tool_use_id: z.ZodString;
32
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnknown>]>;
33
+ is_error: z.ZodOptional<z.ZodBoolean>;
34
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
35
+ }, z.core.$strip>, z.ZodObject<{
36
+ type: z.ZodLiteral<"system_note">;
37
+ note_type: z.ZodEnum<{
38
+ session_created: "session_created";
39
+ forked: "forked";
40
+ compacted: "compacted";
41
+ info: "info";
42
+ }>;
43
+ text: z.ZodString;
44
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
45
+ }, z.core.$strip>], "type">;
46
+ export declare const wsClientEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
47
+ type: z.ZodLiteral<"auth">;
48
+ requestId: z.ZodOptional<z.ZodString>;
49
+ payload: z.ZodObject<{
50
+ token: z.ZodString;
51
+ }, z.core.$strip>;
52
+ }, z.core.$strip>, z.ZodObject<{
53
+ type: z.ZodLiteral<"session.message.create">;
54
+ requestId: z.ZodOptional<z.ZodString>;
55
+ payload: z.ZodObject<{
56
+ spaceId: z.ZodString;
57
+ sessionId: z.ZodString;
58
+ clientMessageId: z.ZodOptional<z.ZodString>;
59
+ content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
60
+ type: z.ZodLiteral<"text">;
61
+ text: z.ZodString;
62
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
63
+ }, z.core.$strip>, z.ZodObject<{
64
+ type: z.ZodLiteral<"thinking">;
65
+ thinking: z.ZodString;
66
+ signature: z.ZodOptional<z.ZodString>;
67
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
68
+ }, z.core.$strip>, z.ZodObject<{
69
+ type: z.ZodLiteral<"image">;
70
+ source: z.ZodUnion<readonly [z.ZodObject<{
71
+ type: z.ZodLiteral<"url">;
72
+ url: z.ZodString;
73
+ }, z.core.$strip>, z.ZodObject<{
74
+ type: z.ZodLiteral<"base64">;
75
+ media_type: z.ZodString;
76
+ data: z.ZodString;
77
+ }, z.core.$strip>]>;
78
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
79
+ }, z.core.$strip>, z.ZodObject<{
80
+ type: z.ZodLiteral<"tool_use">;
81
+ id: z.ZodString;
82
+ name: z.ZodString;
83
+ input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
84
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
85
+ }, z.core.$strip>, z.ZodObject<{
86
+ type: z.ZodLiteral<"tool_result">;
87
+ tool_use_id: z.ZodString;
88
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnknown>]>;
89
+ is_error: z.ZodOptional<z.ZodBoolean>;
90
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
91
+ }, z.core.$strip>, z.ZodObject<{
92
+ type: z.ZodLiteral<"system_note">;
93
+ note_type: z.ZodEnum<{
94
+ session_created: "session_created";
95
+ forked: "forked";
96
+ compacted: "compacted";
97
+ info: "info";
98
+ }>;
99
+ text: z.ZodString;
100
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
101
+ }, z.core.$strip>], "type">>;
102
+ model: z.ZodOptional<z.ZodString>;
103
+ provider: z.ZodOptional<z.ZodString>;
104
+ }, z.core.$strip>;
105
+ }, z.core.$strip>, z.ZodObject<{
106
+ type: z.ZodLiteral<"ping">;
107
+ requestId: z.ZodOptional<z.ZodString>;
108
+ payload: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
109
+ }, z.core.$strip>, z.ZodObject<{
110
+ type: z.ZodLiteral<"ack">;
111
+ requestId: z.ZodOptional<z.ZodString>;
112
+ payload: z.ZodOptional<z.ZodObject<{
113
+ eventId: z.ZodOptional<z.ZodString>;
114
+ }, z.core.$strip>>;
115
+ }, z.core.$strip>], "type">;
116
+ export declare const realtimeEnvelopeSchema: z.ZodObject<{
117
+ id: z.ZodString;
118
+ timestamp: z.ZodNumber;
119
+ domain: z.ZodEnum<{
120
+ system: "system";
121
+ session: "session";
122
+ space: "space";
123
+ }>;
124
+ type: z.ZodString;
125
+ requestId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
126
+ spaceId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
127
+ sessionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
128
+ payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
129
+ }, z.core.$strip>;
130
+ export type { ContentBlock };
131
+ export type WsClientEvent = {
132
+ type: "auth";
133
+ requestId?: string;
134
+ payload: {
135
+ token: string;
136
+ };
137
+ } | {
138
+ type: "session.message.create";
139
+ requestId?: string;
140
+ payload: {
141
+ spaceId: string;
142
+ sessionId: string;
143
+ clientMessageId?: string;
144
+ content: ContentBlock[];
145
+ model?: string;
146
+ provider?: string;
147
+ };
148
+ } | {
149
+ type: "ping";
150
+ requestId?: string;
151
+ payload?: Record<string, unknown>;
152
+ } | {
153
+ type: "ack";
154
+ requestId?: string;
155
+ payload?: {
156
+ eventId?: string;
157
+ };
158
+ };
159
+ export type RealtimeEnvelope = z.output<typeof realtimeEnvelopeSchema>;
160
+ export type RealtimeEnvelopeBase = RealtimeEnvelope;
161
+ export type RealtimeDomain = RealtimeEnvelopeBase["domain"];
162
+ export type SystemReadyEvent = {
163
+ id: string;
164
+ timestamp: number;
165
+ domain: "system";
166
+ type: "system.ready";
167
+ requestId?: string | null;
168
+ spaceId?: string | null;
169
+ sessionId?: string | null;
170
+ payload: {
171
+ connectionId: string;
172
+ };
173
+ };
174
+ export type SystemAuthOkEvent = {
175
+ id: string;
176
+ timestamp: number;
177
+ domain: "system";
178
+ type: "system.auth.ok";
179
+ requestId?: string | null;
180
+ spaceId?: string | null;
181
+ sessionId?: string | null;
182
+ payload: {
183
+ connectionId: string;
184
+ user: Record<string, unknown>;
185
+ };
186
+ };
187
+ export type SystemRequestErrorEvent = {
188
+ id: string;
189
+ timestamp: number;
190
+ domain: "system";
191
+ type: "system.request.error";
192
+ requestId?: string | null;
193
+ spaceId?: string | null;
194
+ sessionId?: string | null;
195
+ payload: {
196
+ code: string;
197
+ message: string;
198
+ };
199
+ };
200
+ export type SystemPongEvent = {
201
+ id: string;
202
+ timestamp: number;
203
+ domain: "system";
204
+ type: "system.pong";
205
+ requestId?: string | null;
206
+ spaceId?: string | null;
207
+ sessionId?: string | null;
208
+ payload: Record<string, never>;
209
+ };
210
+ export type SystemAckOkEvent = {
211
+ id: string;
212
+ timestamp: number;
213
+ domain: "system";
214
+ type: "system.ack.ok";
215
+ requestId?: string | null;
216
+ spaceId?: string | null;
217
+ sessionId?: string | null;
218
+ payload: Record<string, never>;
219
+ };
220
+ export type SessionRequestAcceptedEvent = {
221
+ id: string;
222
+ timestamp: number;
223
+ domain: "session";
224
+ type: "session.request.accepted";
225
+ requestId?: string | null;
226
+ spaceId: string;
227
+ sessionId: string;
228
+ payload: {
229
+ clientMessageId?: string | null;
230
+ };
231
+ };
232
+ export type SessionRequestErrorEvent = {
233
+ id: string;
234
+ timestamp: number;
235
+ domain: "session";
236
+ type: "session.request.error";
237
+ requestId?: string | null;
238
+ spaceId?: string | null;
239
+ sessionId?: string | null;
240
+ payload: {
241
+ code: string;
242
+ message: string;
243
+ clientMessageId?: string | null;
244
+ };
245
+ };
246
+ export type SessionTurnProgressEvent = {
247
+ id: string;
248
+ timestamp: number;
249
+ domain: "session";
250
+ type: "session.turn.progress";
251
+ requestId?: string | null;
252
+ spaceId: string;
253
+ sessionId: string;
254
+ payload: {
255
+ anchorUserMessageId: string | null;
256
+ content: ContentBlock[];
257
+ };
258
+ };
259
+ export type SessionTurnFinalEvent = {
260
+ id: string;
261
+ timestamp: number;
262
+ domain: "session";
263
+ type: "session.turn.final";
264
+ requestId?: string | null;
265
+ spaceId: string;
266
+ sessionId: string;
267
+ payload: {
268
+ sessionMessageId: string | null;
269
+ anchorUserMessageId: string | null;
270
+ content: ContentBlock[];
271
+ };
272
+ };
273
+ export type SessionTurnErrorEvent = {
274
+ id: string;
275
+ timestamp: number;
276
+ domain: "session";
277
+ type: "session.turn.error";
278
+ requestId?: string | null;
279
+ spaceId: string;
280
+ sessionId: string;
281
+ payload: {
282
+ anchorUserMessageId: string | null;
283
+ error: string;
284
+ };
285
+ };
286
+ export type SessionMessagePersistedEvent = {
287
+ id: string;
288
+ timestamp: number;
289
+ domain: "session";
290
+ type: "session.message.persisted";
291
+ requestId?: string | null;
292
+ spaceId: string;
293
+ sessionId: string;
294
+ payload: {
295
+ message: MessageRecord;
296
+ };
297
+ };
298
+ export type RealtimeServerEvent = SystemReadyEvent | SystemAuthOkEvent | SystemRequestErrorEvent | SystemPongEvent | SystemAckOkEvent | SessionRequestAcceptedEvent | SessionRequestErrorEvent | SessionTurnProgressEvent | SessionTurnFinalEvent | SessionTurnErrorEvent | SessionMessagePersistedEvent;
299
+ export type WsServerEnvelope = RealtimeEnvelope;
@@ -0,0 +1,85 @@
1
+ import { z } from "zod";
2
+ const contentBlockMetaSchema = z.record(z.string(), z.unknown());
3
+ // ── Schemas ──
4
+ export const contentBlockSchema = z.discriminatedUnion("type", [
5
+ z.object({
6
+ type: z.literal("text"),
7
+ text: z.string(),
8
+ _meta: contentBlockMetaSchema.optional(),
9
+ }),
10
+ z.object({
11
+ type: z.literal("thinking"),
12
+ thinking: z.string(),
13
+ signature: z.string().optional(),
14
+ _meta: contentBlockMetaSchema.optional(),
15
+ }),
16
+ z.object({
17
+ type: z.literal("image"),
18
+ source: z.union([
19
+ z.object({ type: z.literal("url"), url: z.string().url() }),
20
+ z.object({ type: z.literal("base64"), media_type: z.string(), data: z.string() }),
21
+ ]),
22
+ _meta: contentBlockMetaSchema.optional(),
23
+ }),
24
+ z.object({
25
+ type: z.literal("tool_use"),
26
+ id: z.string(),
27
+ name: z.string(),
28
+ input: z.record(z.string(), z.unknown()),
29
+ _meta: contentBlockMetaSchema.optional(),
30
+ }),
31
+ z.object({
32
+ type: z.literal("tool_result"),
33
+ tool_use_id: z.string(),
34
+ content: z.union([z.string(), z.array(z.unknown())]),
35
+ is_error: z.boolean().optional(),
36
+ _meta: contentBlockMetaSchema.optional(),
37
+ }),
38
+ z.object({
39
+ type: z.literal("system_note"),
40
+ note_type: z.enum(["session_created", "forked", "compacted", "info"]),
41
+ text: z.string(),
42
+ _meta: contentBlockMetaSchema.optional(),
43
+ }),
44
+ ]);
45
+ export const wsClientEventSchema = z.discriminatedUnion("type", [
46
+ z.object({
47
+ type: z.literal("auth"),
48
+ requestId: z.string().optional(),
49
+ payload: z.object({ token: z.string().min(1) }),
50
+ }),
51
+ z.object({
52
+ type: z.literal("session.message.create"),
53
+ requestId: z.string().optional(),
54
+ payload: z.object({
55
+ spaceId: z.string().uuid(),
56
+ sessionId: z.string().uuid(),
57
+ clientMessageId: z.string().optional(),
58
+ content: z.array(contentBlockSchema).min(1),
59
+ model: z.string().optional(),
60
+ provider: z.string().optional(),
61
+ }),
62
+ }),
63
+ z.object({
64
+ type: z.literal("ping"),
65
+ requestId: z.string().optional(),
66
+ payload: z.record(z.string(), z.unknown()).optional(),
67
+ }),
68
+ z.object({
69
+ type: z.literal("ack"),
70
+ requestId: z.string().optional(),
71
+ payload: z.object({
72
+ eventId: z.string().optional(),
73
+ }).optional(),
74
+ }),
75
+ ]);
76
+ export const realtimeEnvelopeSchema = z.object({
77
+ id: z.string(),
78
+ timestamp: z.number(),
79
+ domain: z.enum(["system", "session", "space"]),
80
+ type: z.string(),
81
+ requestId: z.string().nullable().optional(),
82
+ spaceId: z.string().nullable().optional(),
83
+ sessionId: z.string().nullable().optional(),
84
+ payload: z.record(z.string(), z.unknown()),
85
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub-protocol",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Shared protocol definitions for the Cohub agent collaboration platform.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,