@beanx/cathygo-protocol 0.1.0 → 0.1.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.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @beanx/cathygo-protocol
2
+
3
+ Public TypeScript protocol package for CathyGO Web/iOS clients.
4
+
5
+ Current active upgrade plan:
6
+
7
+ - [`../../docs/session-runtime-vnext-upgrade-plan.md`](../../docs/session-runtime-vnext-upgrade-plan.md)
8
+
9
+ ## vNext Role
10
+
11
+ This package owns the typed client contract for:
12
+
13
+ - request/response multiplexing over local WebSocket or BeanX Relay transport
14
+ - `session.input` with `client_input_id`
15
+ - `session.stop`
16
+ - `session.resume`
17
+ - `session.subscribe(session_id, after_seq, follow=true)`
18
+ - stable event names for user messages, session loop lifecycle, assistant
19
+ deltas, terminal events, and replay
20
+
21
+ It must not own product rendering state. Session view state and rendering
22
+ helpers belong in `@beanx/cathygo-web-core`.
23
+
24
+ ## First vNext Deliverables
25
+
26
+ - Add event/request/result types from the upgrade plan.
27
+ - Update `CathyGOProtocolClient` methods.
28
+ - Add tests for input idempotency fields, stop payloads, removed legacy command
29
+ rejection, and event typing.
30
+ - Bump to `0.2.0` only after local Web validates the new runtime path.
package/dist/index.d.ts CHANGED
@@ -48,6 +48,12 @@ type CathyGOResponse = {
48
48
  type LearningTurnEventPayload = {
49
49
  session_id?: string;
50
50
  turn_id?: string;
51
+ turn_ids?: string[];
52
+ client_input_id?: string;
53
+ client_turn_id?: string;
54
+ interrupted_turn_id?: string;
55
+ interrupted_turn_ids?: string[];
56
+ same_session_policy?: SameSessionPolicy;
51
57
  capability?: "chat" | "photo_question";
52
58
  input_summary?: string;
53
59
  input_mode?: "text" | "image" | "text_image" | string;
@@ -56,7 +62,7 @@ type LearningTurnEventPayload = {
56
62
  delta?: string;
57
63
  message?: string;
58
64
  blocks?: unknown[];
59
- status?: "running" | "completed" | "failed" | "cancelled";
65
+ status?: "accepted" | "idle" | "running" | "stopping" | "completed" | "failed" | "cancelled" | string;
60
66
  reason?: string;
61
67
  phase?: "queued" | "model" | "reasoning" | "tool" | "generating" | string;
62
68
  source?: "provider_reasoning_summary" | "public_progress" | "system_progress" | "hidden_reasoning" | string;
@@ -72,7 +78,7 @@ type LearningTurnEventPayload = {
72
78
  };
73
79
  type LearningTurnEvent = {
74
80
  type: "event";
75
- event: "turn.started" | "assistant.delta" | "assistant.completed" | "turn.completed" | "turn.failed" | "turn.cancelled" | "agent.activity.started" | "agent.activity.updated" | "agent.activity.completed" | "agent.progress.delta" | `debug.${string}` | `experimental.${string}`;
81
+ event: "session.created" | "session.deleted" | "session.input.accepted" | "session.stop.requested" | "turn.started" | "assistant.delta" | "assistant.completed" | "turn.completed" | "turn.failed" | "turn.cancelled" | "agent.activity.started" | "agent.activity.updated" | "agent.activity.completed" | "agent.progress.delta" | `debug.${string}` | `experimental.${string}`;
76
82
  seq: number;
77
83
  payload: LearningTurnEventPayload;
78
84
  };
@@ -113,14 +119,39 @@ type MultimodalTurnInput = {
113
119
  attachments?: AttachmentInput[];
114
120
  };
115
121
  type TurnInput = TextTurnInput | MultimodalTurnInput;
116
- type TurnStartOptions = {
122
+ type SameSessionPolicy = "interrupt" | "reject";
123
+ type SessionInputOptions = {
117
124
  capability?: "chat" | "photo_question";
118
125
  metadata?: Record<string, unknown>;
126
+ clientInputId?: string;
127
+ clientTurnId?: string;
128
+ sameSessionPolicy?: SameSessionPolicy;
119
129
  };
120
- type TurnStartResult = {
130
+ type SessionInputResult = {
121
131
  session_id: string;
122
132
  turn_id: string;
123
- status: string;
133
+ status: "accepted" | "running" | "completed" | "failed" | "cancelled" | string;
134
+ client_input_id?: string;
135
+ client_turn_id?: string;
136
+ same_session_policy?: SameSessionPolicy;
137
+ interrupted_turn_id?: string;
138
+ interrupted_turn_ids?: string[];
139
+ idempotent_replay?: boolean;
140
+ };
141
+ type SessionStopResult = {
142
+ session_id: string;
143
+ status: "stopping" | "idle" | string;
144
+ turn_id?: string;
145
+ turn_ids?: string[];
146
+ };
147
+ type SessionRuntimeSnapshot = {
148
+ status: "idle" | "running" | "stopping" | string;
149
+ active_turn_id?: string | null;
150
+ active_turn_ids?: string[];
151
+ active_client_input_id?: string | null;
152
+ active_client_turn_id?: string | null;
153
+ last_event_seq: number;
154
+ last_durable_seq?: number;
124
155
  };
125
156
  type UploadScope = {
126
157
  sessionId?: string;
@@ -135,6 +166,7 @@ interface ConversationSummary {
135
166
  updated_at: string;
136
167
  created_at: string;
137
168
  metadata?: Record<string, unknown>;
169
+ runtime?: SessionRuntimeSnapshot;
138
170
  }
139
171
  interface ConversationMessage {
140
172
  id: string;
@@ -145,9 +177,12 @@ interface ConversationMessage {
145
177
  created_at: string;
146
178
  }
147
179
  interface ConversationDetail {
148
- session: ConversationSummary;
180
+ session: ConversationSummary & {
181
+ runtime?: SessionRuntimeSnapshot;
182
+ };
149
183
  messages: ConversationMessage[];
150
184
  activities?: AgentActivity[];
185
+ runtime?: SessionRuntimeSnapshot;
151
186
  }
152
187
  interface AgentActivity {
153
188
  activity_id: string;
@@ -356,11 +391,11 @@ declare class CathyGOProtocolClient {
356
391
  listSessions(limit?: number): Promise<ConversationSummary[]>;
357
392
  getSession(sessionId: string): Promise<ConversationDetail>;
358
393
  deleteSession(sessionId: string): Promise<void>;
359
- startTurn(sessionId: string, input: TurnInput, options?: TurnStartOptions): Promise<TurnStartResult>;
360
- subscribeTurn(turnId: string, afterSeq?: number): Promise<void>;
394
+ inputSession(sessionId: string, input: TurnInput, options?: SessionInputOptions): Promise<SessionInputResult>;
361
395
  subscribeSession(sessionId: string, afterSeq?: number): Promise<void>;
362
- cancelTurn(turnId: string): Promise<void>;
363
- regenerateLastTurn(sessionId: string): Promise<TurnStartResult>;
396
+ stopSession(sessionId: string): Promise<SessionStopResult>;
397
+ resumeSession(sessionId: string, afterSeq?: number): Promise<ConversationDetail>;
398
+ regenerateSession(sessionId: string): Promise<SessionInputResult>;
364
399
  commitAttachment(params: AttachmentCommitParams): Promise<GatewayAttachment>;
365
400
  getSettings(): Promise<GatewayVisibleSettings>;
366
401
  updateSettings(settings: Record<string, unknown>): Promise<GatewayVisibleSettings>;
@@ -377,10 +412,10 @@ declare function parseConnectPayload(payload: Record<string, unknown>): CathyGOC
377
412
  declare function settingsFromPayload(payload: Record<string, unknown>): GatewayVisibleSettings;
378
413
  declare function isLearningTurnEvent(frame: CathyGOIncomingFrame): frame is LearningTurnEvent;
379
414
 
380
- type LearningCapability = NonNullable<TurnStartOptions["capability"]>;
415
+ type LearningCapability = NonNullable<SessionInputOptions["capability"]>;
381
416
  declare function textTurnInput(text: string): TurnInput;
382
417
  declare function photoQuestionTurnInput(text: string, attachments: GatewayAttachment[]): TurnInput;
383
418
  declare function capabilityForTurn(attachments: GatewayAttachment[]): LearningCapability;
384
419
  declare function learningTurnInput(text: string, attachments: GatewayAttachment[]): TurnInput;
385
420
 
386
- export { type AgentActivity, type AgentPresenceEvent, type AttachmentCommitBlob, type AttachmentCommitParams, type AttachmentInput, type BeanXAccountRuntimeConfig, CathyGOClientError, type CathyGOClientRole, type CathyGOConnectOptions, type CathyGOConnectResult, type CathyGODeviceContext, type CathyGOFrame, type CathyGOIncomingFrame, CathyGOProtocolClient, type CathyGOProtocolClientCallbacks, type CathyGOProtocolClientOptions, type CathyGORequest, type CathyGOResponse, type CathyGOTransport, type CathyGOTransportEventHandler, type CathyGOTransportFrameHandler, type ConversationDetail, type ConversationMessage, type ConversationMessagePart, type ConversationSummary, type GatewayAgentProfile, type GatewayAttachment, type GatewayModelConfig, type GatewayModelConfigUpdate, type GatewayModelOption, type GatewayModelStatus, type GatewayVisibleSettings, type LearningCapability, type LearningTurnEvent, type LearningTurnEventHandler, type LearningTurnEventPayload, type ListResponse, type MessagePartInput, type MultimodalTurnInput, type SettingsItem, type SettingsItemKind, type SettingsSection, type TextTurnInput, type TurnInput, type TurnStartOptions, type TurnStartResult, type UploadScope, capabilityForTurn, connectPayload, isLearningTurnEvent, learningTurnInput, parseConnectPayload, photoQuestionTurnInput, settingsFromPayload, textTurnInput };
421
+ export { type AgentActivity, type AgentPresenceEvent, type AttachmentCommitBlob, type AttachmentCommitParams, type AttachmentInput, type BeanXAccountRuntimeConfig, CathyGOClientError, type CathyGOClientRole, type CathyGOConnectOptions, type CathyGOConnectResult, type CathyGODeviceContext, type CathyGOFrame, type CathyGOIncomingFrame, CathyGOProtocolClient, type CathyGOProtocolClientCallbacks, type CathyGOProtocolClientOptions, type CathyGORequest, type CathyGOResponse, type CathyGOTransport, type CathyGOTransportEventHandler, type CathyGOTransportFrameHandler, type ConversationDetail, type ConversationMessage, type ConversationMessagePart, type ConversationSummary, type GatewayAgentProfile, type GatewayAttachment, type GatewayModelConfig, type GatewayModelConfigUpdate, type GatewayModelOption, type GatewayModelStatus, type GatewayVisibleSettings, type LearningCapability, type LearningTurnEvent, type LearningTurnEventHandler, type LearningTurnEventPayload, type ListResponse, type MessagePartInput, type MultimodalTurnInput, type SameSessionPolicy, type SessionInputOptions, type SessionInputResult, type SessionRuntimeSnapshot, type SessionStopResult, type SettingsItem, type SettingsItemKind, type SettingsSection, type TextTurnInput, type TurnInput, type UploadScope, capabilityForTurn, connectPayload, isLearningTurnEvent, learningTurnInput, parseConnectPayload, photoQuestionTurnInput, settingsFromPayload, textTurnInput };
package/dist/index.js CHANGED
@@ -88,24 +88,20 @@ var CathyGOProtocolClient = class {
88
88
  async deleteSession(sessionId) {
89
89
  await this.request("session.delete", { session_id: sessionId });
90
90
  }
91
- async startTurn(sessionId, input, options = {}) {
92
- const payload = await this.request("turn.start", {
93
- session_id: sessionId,
94
- capability: options.capability,
95
- input,
96
- metadata: options.metadata
97
- });
98
- return {
99
- session_id: String(payload.session_id ?? sessionId),
100
- turn_id: String(payload.turn_id ?? ""),
101
- status: String(payload.status ?? "accepted")
102
- };
103
- }
104
- async subscribeTurn(turnId, afterSeq) {
105
- await this.request("turn.subscribe", {
106
- turn_id: turnId,
107
- after_seq: afterSeq ?? this.lastEventSeq
108
- });
91
+ async inputSession(sessionId, input, options = {}) {
92
+ const payload = await this.request(
93
+ "session.input",
94
+ compactParams({
95
+ session_id: sessionId,
96
+ capability: options.capability,
97
+ input,
98
+ metadata: options.metadata,
99
+ client_input_id: options.clientInputId,
100
+ client_turn_id: options.clientTurnId,
101
+ same_session_policy: options.sameSessionPolicy
102
+ })
103
+ );
104
+ return turnStartResultFromPayload(payload, sessionId);
109
105
  }
110
106
  async subscribeSession(sessionId, afterSeq) {
111
107
  await this.request("session.subscribe", {
@@ -113,11 +109,25 @@ var CathyGOProtocolClient = class {
113
109
  after_seq: afterSeq ?? this.lastEventSeq
114
110
  });
115
111
  }
116
- async cancelTurn(turnId) {
117
- await this.request("turn.cancel", { turn_id: turnId });
112
+ async stopSession(sessionId) {
113
+ const payload = await this.request("session.stop", { session_id: sessionId });
114
+ return {
115
+ session_id: String(payload.session_id ?? sessionId),
116
+ status: String(payload.status ?? "idle"),
117
+ turn_id: optionalString(payload.turn_id),
118
+ turn_ids: Array.isArray(payload.turn_ids) ? payload.turn_ids.map((value) => String(value)) : void 0
119
+ };
118
120
  }
119
- async regenerateLastTurn(sessionId) {
120
- const payload = await this.request("turn.regenerate", { session_id: sessionId });
121
+ async resumeSession(sessionId, afterSeq) {
122
+ const detail = await this.getSession(sessionId);
123
+ await this.subscribeSession(
124
+ sessionId,
125
+ afterSeq ?? detail.runtime?.last_event_seq ?? detail.session.runtime?.last_event_seq
126
+ );
127
+ return detail;
128
+ }
129
+ async regenerateSession(sessionId) {
130
+ const payload = await this.request("session.regenerate", { session_id: sessionId });
121
131
  return {
122
132
  session_id: String(payload.session_id ?? sessionId),
123
133
  turn_id: String(payload.turn_id ?? ""),
@@ -242,7 +252,32 @@ function settingsFromPayload(payload) {
242
252
  };
243
253
  }
244
254
  function isLearningTurnEvent(frame) {
245
- return frame.type === "event" && (frame.event.startsWith("turn.") || frame.event.startsWith("agent.activity.") || frame.event.startsWith("agent.progress.") || frame.event.startsWith("assistant.") || frame.event.startsWith("debug.") || frame.event.startsWith("experimental."));
255
+ return frame.type === "event" && (frame.event.startsWith("session.") || frame.event.startsWith("turn.") || frame.event.startsWith("agent.activity.") || frame.event.startsWith("agent.progress.") || frame.event.startsWith("assistant.") || frame.event.startsWith("debug.") || frame.event.startsWith("experimental."));
256
+ }
257
+ function turnStartResultFromPayload(payload, fallbackSessionId) {
258
+ return {
259
+ session_id: String(payload.session_id ?? fallbackSessionId),
260
+ turn_id: String(payload.turn_id ?? ""),
261
+ status: String(payload.status ?? "accepted"),
262
+ client_input_id: optionalString(payload.client_input_id),
263
+ client_turn_id: optionalString(payload.client_turn_id),
264
+ same_session_policy: sameSessionPolicy(payload.same_session_policy),
265
+ interrupted_turn_id: optionalString(payload.interrupted_turn_id),
266
+ interrupted_turn_ids: Array.isArray(payload.interrupted_turn_ids) ? payload.interrupted_turn_ids.map((value) => String(value)) : void 0,
267
+ idempotent_replay: payload.idempotent_replay === true
268
+ };
269
+ }
270
+ function optionalString(value) {
271
+ if (value === void 0 || value === null) return void 0;
272
+ const text = String(value).trim();
273
+ return text || void 0;
274
+ }
275
+ function sameSessionPolicy(value) {
276
+ if (value === "interrupt" || value === "reject") return value;
277
+ return void 0;
278
+ }
279
+ function compactParams(params) {
280
+ return Object.fromEntries(Object.entries(params).filter(([, value]) => value !== void 0));
246
281
  }
247
282
 
248
283
  // src/turn-input.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beanx/cathygo-protocol",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"