@agentuity/coder 1.0.40 → 1.0.41
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/client.d.ts +2 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -1
- package/dist/hub-overlay-state.d.ts +30 -0
- package/dist/hub-overlay-state.d.ts.map +1 -0
- package/dist/hub-overlay-state.js +68 -0
- package/dist/hub-overlay-state.js.map +1 -0
- package/dist/hub-overlay.d.ts +41 -2
- package/dist/hub-overlay.d.ts.map +1 -1
- package/dist/hub-overlay.js +667 -115
- package/dist/hub-overlay.js.map +1 -1
- package/dist/protocol.d.ts +209 -37
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +2 -1
- package/dist/protocol.js.map +1 -1
- package/dist/remote-lifecycle.d.ts +61 -0
- package/dist/remote-lifecycle.d.ts.map +1 -0
- package/dist/remote-lifecycle.js +190 -0
- package/dist/remote-lifecycle.js.map +1 -0
- package/dist/remote-session.d.ts +15 -0
- package/dist/remote-session.d.ts.map +1 -1
- package/dist/remote-session.js +240 -35
- package/dist/remote-session.js.map +1 -1
- package/dist/remote-tui.d.ts.map +1 -1
- package/dist/remote-tui.js +78 -6
- package/dist/remote-tui.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +5 -3
- package/src/hub-overlay-state.ts +117 -0
- package/src/hub-overlay.ts +974 -138
- package/src/protocol.ts +269 -55
- package/src/remote-lifecycle.ts +270 -0
- package/src/remote-session.ts +293 -38
- package/src/remote-tui.ts +103 -8
package/src/protocol.ts
CHANGED
|
@@ -1,22 +1,80 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Hub protocol types used by the Coder TUI package.
|
|
2
|
+
// Keep the legacy exported names stable while modeling the newer hub envelopes.
|
|
2
3
|
|
|
3
4
|
export interface HubToolDefinition {
|
|
4
5
|
name: string;
|
|
5
6
|
label: string;
|
|
6
7
|
description: string;
|
|
7
|
-
parameters: Record<string, unknown>;
|
|
8
|
+
parameters: Record<string, unknown>;
|
|
8
9
|
promptSnippet?: string;
|
|
9
10
|
promptGuidelines?: string | string[];
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
/** Command definition sent by Hub for agent routing slash commands. */
|
|
13
13
|
export interface HubCommandDefinition {
|
|
14
14
|
name: string;
|
|
15
15
|
description: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export interface AckAction {
|
|
19
|
+
action: 'ACK';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface BlockAction {
|
|
23
|
+
action: 'BLOCK';
|
|
24
|
+
reason: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ConfirmAction {
|
|
28
|
+
action: 'CONFIRM';
|
|
29
|
+
title: string;
|
|
30
|
+
message: string;
|
|
31
|
+
deny_reason?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface NotifyAction {
|
|
35
|
+
action: 'NOTIFY';
|
|
36
|
+
message: string;
|
|
37
|
+
level?: 'info' | 'warning' | 'error';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ReturnAction {
|
|
41
|
+
action: 'RETURN';
|
|
42
|
+
result: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface StatusAction {
|
|
46
|
+
action: 'STATUS';
|
|
47
|
+
key: string;
|
|
48
|
+
text?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SystemPromptAction {
|
|
52
|
+
action: 'SYSTEM_PROMPT';
|
|
53
|
+
systemPrompt: string;
|
|
54
|
+
mode?: 'replace' | 'prefix' | 'suffix';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface InjectMessageAction {
|
|
58
|
+
action: 'INJECT_MESSAGE';
|
|
59
|
+
message: {
|
|
60
|
+
role: 'user' | 'assistant';
|
|
61
|
+
content: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type HubAction =
|
|
66
|
+
| AckAction
|
|
67
|
+
| BlockAction
|
|
68
|
+
| ConfirmAction
|
|
69
|
+
| NotifyAction
|
|
70
|
+
| ReturnAction
|
|
71
|
+
| StatusAction
|
|
72
|
+
| SystemPromptAction
|
|
73
|
+
| InjectMessageAction;
|
|
74
|
+
|
|
18
75
|
export interface AgentDefinition {
|
|
19
76
|
name: string;
|
|
77
|
+
displayName?: string;
|
|
20
78
|
description: string;
|
|
21
79
|
systemPrompt: string;
|
|
22
80
|
model?: string;
|
|
@@ -41,10 +99,14 @@ export interface InitMessage {
|
|
|
41
99
|
commands?: HubCommandDefinition[];
|
|
42
100
|
agents?: AgentDefinition[];
|
|
43
101
|
config?: HubConfig;
|
|
102
|
+
model?: {
|
|
103
|
+
provider: string;
|
|
104
|
+
id: string;
|
|
105
|
+
};
|
|
106
|
+
thinkingLevel?: string;
|
|
107
|
+
task?: string;
|
|
44
108
|
}
|
|
45
109
|
|
|
46
|
-
// ---- Request Messages (Client → Server) ----
|
|
47
|
-
|
|
48
110
|
export interface EventRequest {
|
|
49
111
|
id: string;
|
|
50
112
|
type: 'event';
|
|
@@ -60,7 +122,6 @@ export interface ToolRequest {
|
|
|
60
122
|
params: Record<string, unknown>;
|
|
61
123
|
}
|
|
62
124
|
|
|
63
|
-
/** Command request (Client -> Server) for slash command execution. */
|
|
64
125
|
export interface CommandRequest {
|
|
65
126
|
id: string;
|
|
66
127
|
type: 'command';
|
|
@@ -70,68 +131,228 @@ export interface CommandRequest {
|
|
|
70
131
|
|
|
71
132
|
export type HubRequest = EventRequest | ToolRequest | CommandRequest;
|
|
72
133
|
|
|
73
|
-
|
|
134
|
+
export interface SessionEntryMessage {
|
|
135
|
+
type: 'session_entry';
|
|
136
|
+
path: string;
|
|
137
|
+
line: string;
|
|
138
|
+
}
|
|
74
139
|
|
|
75
|
-
export interface
|
|
76
|
-
|
|
140
|
+
export interface SessionWriteMessage {
|
|
141
|
+
type: 'session_write';
|
|
142
|
+
path: string;
|
|
143
|
+
content: string;
|
|
77
144
|
}
|
|
78
145
|
|
|
79
|
-
export interface
|
|
80
|
-
|
|
81
|
-
|
|
146
|
+
export interface RpcCommandMessage {
|
|
147
|
+
type: 'rpc_command';
|
|
148
|
+
command: Record<string, unknown>;
|
|
82
149
|
}
|
|
83
150
|
|
|
84
|
-
export interface
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
deny_reason?: string;
|
|
151
|
+
export interface RpcUiResponseMessage {
|
|
152
|
+
type: 'rpc_ui_response';
|
|
153
|
+
id: string;
|
|
154
|
+
result: unknown;
|
|
89
155
|
}
|
|
90
156
|
|
|
91
|
-
export interface
|
|
92
|
-
|
|
157
|
+
export interface PingMessage {
|
|
158
|
+
type: 'ping';
|
|
159
|
+
timestamp: number;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export type HubClientMessage =
|
|
163
|
+
| HubRequest
|
|
164
|
+
| SessionEntryMessage
|
|
165
|
+
| SessionWriteMessage
|
|
166
|
+
| RpcCommandMessage
|
|
167
|
+
| RpcUiResponseMessage
|
|
168
|
+
| PingMessage;
|
|
169
|
+
|
|
170
|
+
export interface HubResponse {
|
|
171
|
+
id: string;
|
|
172
|
+
actions: HubAction[];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface CoderHubStreamReadyMessage {
|
|
176
|
+
type: 'session_stream_ready';
|
|
177
|
+
streamId: string;
|
|
178
|
+
streamUrl: string;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface CoderHubSessionResumeMessage {
|
|
182
|
+
type: 'session_resume';
|
|
183
|
+
streamUrl: string;
|
|
184
|
+
streamId: string;
|
|
185
|
+
activePrdKey?: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface ConnectionRejectedMessage {
|
|
189
|
+
type: 'connection_rejected';
|
|
190
|
+
code: string;
|
|
93
191
|
message: string;
|
|
94
|
-
|
|
192
|
+
sessionId?: string;
|
|
193
|
+
reconnectState?: string;
|
|
194
|
+
expiredAt?: number;
|
|
195
|
+
timestamp: number;
|
|
95
196
|
}
|
|
96
197
|
|
|
97
|
-
export interface
|
|
98
|
-
|
|
99
|
-
|
|
198
|
+
export interface ConversationEntry {
|
|
199
|
+
type:
|
|
200
|
+
| 'message'
|
|
201
|
+
| 'thinking'
|
|
202
|
+
| 'tool_call'
|
|
203
|
+
| 'tool_result'
|
|
204
|
+
| 'task_result'
|
|
205
|
+
| 'turn'
|
|
206
|
+
| 'user_prompt';
|
|
207
|
+
agent?: string;
|
|
208
|
+
content?: string;
|
|
209
|
+
toolName?: string;
|
|
210
|
+
toolArgs?: Record<string, unknown>;
|
|
211
|
+
toolCallId?: string;
|
|
212
|
+
isError?: boolean;
|
|
213
|
+
taskId?: string;
|
|
214
|
+
timestamp: number;
|
|
100
215
|
}
|
|
101
216
|
|
|
102
|
-
export interface
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
217
|
+
export interface HydrationTaskState {
|
|
218
|
+
taskId: string;
|
|
219
|
+
agent: string;
|
|
220
|
+
status: 'running' | 'completed' | 'failed';
|
|
221
|
+
prompt: string;
|
|
222
|
+
duration?: number;
|
|
223
|
+
result?: string;
|
|
224
|
+
error?: string;
|
|
106
225
|
}
|
|
107
226
|
|
|
108
|
-
export interface
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
227
|
+
export interface SessionParticipant {
|
|
228
|
+
id: string;
|
|
229
|
+
role: 'lead' | 'observer' | 'controller';
|
|
230
|
+
transport: 'ws' | 'sse';
|
|
231
|
+
subscriptions: string[];
|
|
232
|
+
connectedAt: number;
|
|
233
|
+
lastActivity: number;
|
|
112
234
|
}
|
|
113
235
|
|
|
114
|
-
export interface
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
236
|
+
export interface SessionStreamBlock {
|
|
237
|
+
output: string;
|
|
238
|
+
thinking: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface SessionStreamProjection extends SessionStreamBlock {
|
|
242
|
+
tasks: Record<string, SessionStreamBlock>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface SessionSnapshot {
|
|
246
|
+
sessionId: string;
|
|
247
|
+
label: string;
|
|
248
|
+
status: 'active' | 'paused' | 'shutdown' | 'archived' | 'error' | 'stopped';
|
|
249
|
+
createdAt: string;
|
|
250
|
+
mode: 'sandbox' | 'tui';
|
|
251
|
+
task?: string;
|
|
252
|
+
error?: string;
|
|
253
|
+
streamId?: string | null;
|
|
254
|
+
streamUrl?: string | null;
|
|
255
|
+
context: {
|
|
256
|
+
branch?: string;
|
|
257
|
+
workingDirectory?: string;
|
|
119
258
|
};
|
|
259
|
+
participants: SessionParticipant[];
|
|
260
|
+
tasks: Array<{
|
|
261
|
+
taskId: string;
|
|
262
|
+
agent: string;
|
|
263
|
+
status: 'running' | 'completed' | 'failed';
|
|
264
|
+
prompt: string;
|
|
265
|
+
duration?: number;
|
|
266
|
+
startedAt?: string;
|
|
267
|
+
completedAt?: string;
|
|
268
|
+
}>;
|
|
269
|
+
agentActivity: Record<
|
|
270
|
+
string,
|
|
271
|
+
{
|
|
272
|
+
name?: string;
|
|
273
|
+
status: string;
|
|
274
|
+
currentTool?: string;
|
|
275
|
+
currentToolArgs?: string;
|
|
276
|
+
toolCallCount: number;
|
|
277
|
+
lastActivity: number;
|
|
278
|
+
totalElapsed?: number;
|
|
279
|
+
}
|
|
280
|
+
>;
|
|
281
|
+
stream?: SessionStreamProjection;
|
|
282
|
+
tags?: string[];
|
|
283
|
+
defaultAgent?: string;
|
|
284
|
+
bucket?: 'running' | 'paused' | 'provisioning' | 'history';
|
|
285
|
+
runtimeAvailable?: boolean;
|
|
286
|
+
controlAvailable?: boolean;
|
|
287
|
+
historyOnly?: boolean;
|
|
120
288
|
}
|
|
121
289
|
|
|
122
|
-
export
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
290
|
+
export interface CoderHubHydrationMessage {
|
|
291
|
+
type: 'session_hydration';
|
|
292
|
+
sessionId: string;
|
|
293
|
+
resumedAt: number;
|
|
294
|
+
entries: ConversationEntry[];
|
|
295
|
+
tasks: HydrationTaskState[];
|
|
296
|
+
stream?: SessionStreamProjection;
|
|
297
|
+
task?: string;
|
|
298
|
+
streamingState?: {
|
|
299
|
+
isStreaming?: boolean;
|
|
300
|
+
activeTasks?: Array<{
|
|
301
|
+
taskId: string;
|
|
302
|
+
agent: string;
|
|
303
|
+
}>;
|
|
304
|
+
};
|
|
305
|
+
}
|
|
131
306
|
|
|
132
|
-
|
|
307
|
+
export interface PresenceEventMessage {
|
|
308
|
+
type: 'presence';
|
|
309
|
+
event: 'session_join' | 'session_leave' | 'presence_update';
|
|
310
|
+
participant?: SessionParticipant;
|
|
311
|
+
participants?: SessionParticipant[];
|
|
312
|
+
sessionId: string;
|
|
313
|
+
timestamp: number;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface BroadcastEventMessage {
|
|
317
|
+
type: 'broadcast';
|
|
318
|
+
event: string;
|
|
319
|
+
data: Record<string, unknown>;
|
|
320
|
+
category?: string;
|
|
321
|
+
sessionId?: string;
|
|
322
|
+
timestamp?: number;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export interface RpcEventMessage {
|
|
326
|
+
type: 'rpc_event';
|
|
327
|
+
event: Record<string, unknown>;
|
|
328
|
+
timestamp: number;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export interface RpcResponseMessage {
|
|
332
|
+
type: 'rpc_response';
|
|
333
|
+
response: Record<string, unknown>;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export interface RpcUiRequestMessage {
|
|
337
|
+
type: 'rpc_ui_request';
|
|
338
|
+
id: string;
|
|
339
|
+
method: string;
|
|
340
|
+
params: Record<string, unknown>;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export type ServerMessage =
|
|
344
|
+
| InitMessage
|
|
345
|
+
| HubResponse
|
|
346
|
+
| CoderHubHydrationMessage
|
|
347
|
+
| CoderHubStreamReadyMessage
|
|
348
|
+
| CoderHubSessionResumeMessage
|
|
349
|
+
| ConnectionRejectedMessage
|
|
350
|
+
| PresenceEventMessage
|
|
351
|
+
| BroadcastEventMessage
|
|
352
|
+
| RpcEventMessage
|
|
353
|
+
| RpcResponseMessage
|
|
354
|
+
| RpcUiRequestMessage;
|
|
133
355
|
|
|
134
|
-
/** Progress update from a running sub-agent */
|
|
135
356
|
export interface AgentProgressUpdate {
|
|
136
357
|
agentName: string;
|
|
137
358
|
status:
|
|
@@ -146,12 +367,5 @@ export interface AgentProgressUpdate {
|
|
|
146
367
|
currentToolArgs?: string;
|
|
147
368
|
elapsed: number;
|
|
148
369
|
tokens?: { input: number; output: number; cost: number };
|
|
149
|
-
delta?: string;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// ---- Response Message (Server → Client) ----
|
|
153
|
-
|
|
154
|
-
export interface HubResponse {
|
|
155
|
-
id: string;
|
|
156
|
-
actions: HubAction[];
|
|
370
|
+
delta?: string;
|
|
157
371
|
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
export type RemoteLifecyclePhase =
|
|
2
|
+
| 'connecting'
|
|
3
|
+
| 'hydrating'
|
|
4
|
+
| 'replaying'
|
|
5
|
+
| 'live'
|
|
6
|
+
| 'paused'
|
|
7
|
+
| 'resuming'
|
|
8
|
+
| 'reconnecting'
|
|
9
|
+
| 'disconnected';
|
|
10
|
+
|
|
11
|
+
export type RemoteTransportState = 'connecting' | 'connected' | 'reconnecting' | 'disconnected';
|
|
12
|
+
|
|
13
|
+
export interface RemoteLifecycleState {
|
|
14
|
+
sessionId: string;
|
|
15
|
+
label: string;
|
|
16
|
+
transport: RemoteTransportState;
|
|
17
|
+
phase: RemoteLifecyclePhase;
|
|
18
|
+
leadConnected: boolean | null;
|
|
19
|
+
isStreaming: boolean;
|
|
20
|
+
hydrationReceived: boolean;
|
|
21
|
+
streamId: string | null;
|
|
22
|
+
streamUrl: string | null;
|
|
23
|
+
lastError: string | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface RemoteLifecycleWorkingMessageUi {
|
|
27
|
+
setWorkingMessage(message?: string): void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type RemoteLifecycleEvent =
|
|
31
|
+
| { type: 'connect_start'; reconnect: boolean }
|
|
32
|
+
| { type: 'init'; sessionId?: string; label?: string }
|
|
33
|
+
| {
|
|
34
|
+
type: 'hydration';
|
|
35
|
+
leadConnected?: boolean;
|
|
36
|
+
isStreaming?: boolean;
|
|
37
|
+
}
|
|
38
|
+
| { type: 'replay_event' }
|
|
39
|
+
| { type: 'replay_idle' }
|
|
40
|
+
| { type: 'live_signal'; isStreaming?: boolean }
|
|
41
|
+
| { type: 'session_resume'; streamId?: string | null; streamUrl?: string | null }
|
|
42
|
+
| { type: 'stream_ready'; streamId?: string | null; streamUrl?: string | null }
|
|
43
|
+
| { type: 'rpc_command_error'; error: string; paused: boolean }
|
|
44
|
+
| { type: 'local_resume_requested' }
|
|
45
|
+
| { type: 'connection_change'; state: 'reconnecting' | 'disconnected' };
|
|
46
|
+
|
|
47
|
+
export function createRemoteLifecycleState(sessionId: string): RemoteLifecycleState {
|
|
48
|
+
return {
|
|
49
|
+
sessionId,
|
|
50
|
+
label: '',
|
|
51
|
+
transport: 'disconnected',
|
|
52
|
+
phase: 'disconnected',
|
|
53
|
+
leadConnected: null,
|
|
54
|
+
isStreaming: false,
|
|
55
|
+
hydrationReceived: false,
|
|
56
|
+
streamId: null,
|
|
57
|
+
streamUrl: null,
|
|
58
|
+
lastError: null,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function patchState(
|
|
63
|
+
state: RemoteLifecycleState,
|
|
64
|
+
patch: Partial<RemoteLifecycleState>
|
|
65
|
+
): RemoteLifecycleState {
|
|
66
|
+
let changed = false;
|
|
67
|
+
const next = { ...state };
|
|
68
|
+
|
|
69
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
70
|
+
const typedKey = key as keyof RemoteLifecycleState;
|
|
71
|
+
if (next[typedKey] !== value) {
|
|
72
|
+
changed = true;
|
|
73
|
+
(next[typedKey] as RemoteLifecycleState[keyof RemoteLifecycleState]) =
|
|
74
|
+
value as RemoteLifecycleState[keyof RemoteLifecycleState];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return changed ? next : state;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function resolveConnectedPhase(input: {
|
|
82
|
+
leadConnected: boolean | null;
|
|
83
|
+
isStreaming: boolean;
|
|
84
|
+
}): RemoteLifecyclePhase {
|
|
85
|
+
if (input.isStreaming) return 'live';
|
|
86
|
+
if (input.leadConnected === false) return 'paused';
|
|
87
|
+
return 'live';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function applyRemoteLifecycleEvent(
|
|
91
|
+
state: RemoteLifecycleState,
|
|
92
|
+
event: RemoteLifecycleEvent
|
|
93
|
+
): RemoteLifecycleState {
|
|
94
|
+
switch (event.type) {
|
|
95
|
+
case 'connect_start':
|
|
96
|
+
return patchState(state, {
|
|
97
|
+
transport: event.reconnect ? 'reconnecting' : 'connecting',
|
|
98
|
+
phase: event.reconnect ? 'reconnecting' : 'connecting',
|
|
99
|
+
lastError: null,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
case 'init':
|
|
103
|
+
return patchState(state, {
|
|
104
|
+
sessionId: event.sessionId || state.sessionId,
|
|
105
|
+
label: event.label || state.label,
|
|
106
|
+
transport: 'connected',
|
|
107
|
+
phase: 'hydrating',
|
|
108
|
+
lastError: null,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
case 'hydration': {
|
|
112
|
+
const leadConnected =
|
|
113
|
+
typeof event.leadConnected === 'boolean' ? event.leadConnected : state.leadConnected;
|
|
114
|
+
const isStreaming =
|
|
115
|
+
typeof event.isStreaming === 'boolean' ? event.isStreaming : state.isStreaming;
|
|
116
|
+
return patchState(state, {
|
|
117
|
+
leadConnected,
|
|
118
|
+
isStreaming,
|
|
119
|
+
hydrationReceived: true,
|
|
120
|
+
transport: 'connected',
|
|
121
|
+
phase: resolveConnectedPhase({ leadConnected, isStreaming }),
|
|
122
|
+
lastError: null,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
case 'replay_event':
|
|
127
|
+
if (state.transport !== 'connected') return state;
|
|
128
|
+
return patchState(state, {
|
|
129
|
+
phase: 'replaying',
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
case 'replay_idle':
|
|
133
|
+
if (state.phase !== 'replaying') return state;
|
|
134
|
+
return patchState(state, {
|
|
135
|
+
phase: resolveConnectedPhase({
|
|
136
|
+
leadConnected: state.leadConnected,
|
|
137
|
+
isStreaming: state.isStreaming,
|
|
138
|
+
}),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
case 'live_signal':
|
|
142
|
+
return patchState(state, {
|
|
143
|
+
transport: 'connected',
|
|
144
|
+
phase: 'live',
|
|
145
|
+
leadConnected: true,
|
|
146
|
+
isStreaming:
|
|
147
|
+
typeof event.isStreaming === 'boolean' ? event.isStreaming : state.isStreaming,
|
|
148
|
+
lastError: null,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
case 'session_resume':
|
|
152
|
+
return patchState(state, {
|
|
153
|
+
streamId: event.streamId ?? state.streamId,
|
|
154
|
+
streamUrl: event.streamUrl ?? state.streamUrl,
|
|
155
|
+
phase: 'resuming',
|
|
156
|
+
lastError: null,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
case 'stream_ready':
|
|
160
|
+
return patchState(state, {
|
|
161
|
+
streamId: event.streamId ?? state.streamId,
|
|
162
|
+
streamUrl: event.streamUrl ?? state.streamUrl,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
case 'rpc_command_error':
|
|
166
|
+
return patchState(state, {
|
|
167
|
+
lastError: event.error,
|
|
168
|
+
leadConnected: event.paused ? false : state.leadConnected,
|
|
169
|
+
isStreaming: event.paused ? false : state.isStreaming,
|
|
170
|
+
phase: event.paused ? 'paused' : state.phase,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
case 'local_resume_requested':
|
|
174
|
+
return patchState(state, {
|
|
175
|
+
phase: 'resuming',
|
|
176
|
+
lastError: null,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
case 'connection_change':
|
|
180
|
+
return patchState(state, {
|
|
181
|
+
transport: event.state,
|
|
182
|
+
phase: event.state,
|
|
183
|
+
isStreaming: false,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function getRemoteLifecycleLabel(state: RemoteLifecycleState): string {
|
|
189
|
+
switch (state.phase) {
|
|
190
|
+
case 'connecting':
|
|
191
|
+
return 'Connecting';
|
|
192
|
+
case 'hydrating':
|
|
193
|
+
return 'Hydrating';
|
|
194
|
+
case 'replaying':
|
|
195
|
+
return 'Replaying';
|
|
196
|
+
case 'paused':
|
|
197
|
+
return 'Paused';
|
|
198
|
+
case 'resuming':
|
|
199
|
+
return 'Resuming';
|
|
200
|
+
case 'reconnecting':
|
|
201
|
+
return 'Reconnecting';
|
|
202
|
+
case 'disconnected':
|
|
203
|
+
return 'Disconnected';
|
|
204
|
+
case 'live':
|
|
205
|
+
return 'Live';
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function getRemoteLifecycleActivityLabel(state: RemoteLifecycleState): string | undefined {
|
|
210
|
+
switch (state.phase) {
|
|
211
|
+
case 'connecting':
|
|
212
|
+
return 'connecting to sandbox...';
|
|
213
|
+
case 'hydrating':
|
|
214
|
+
return 'hydrating remote session...';
|
|
215
|
+
case 'replaying':
|
|
216
|
+
return 'replaying remote history...';
|
|
217
|
+
case 'paused':
|
|
218
|
+
return 'sandbox paused';
|
|
219
|
+
case 'resuming':
|
|
220
|
+
return 'resuming sandbox...';
|
|
221
|
+
case 'reconnecting':
|
|
222
|
+
return 'reconnecting...';
|
|
223
|
+
case 'disconnected':
|
|
224
|
+
return state.lastError ? `disconnected: ${state.lastError}` : 'disconnected';
|
|
225
|
+
case 'live':
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function getRemoteLifecycleWorkingMessage(state: RemoteLifecycleState): string | undefined {
|
|
231
|
+
switch (state.phase) {
|
|
232
|
+
case 'connecting':
|
|
233
|
+
return 'Connecting to remote sandbox...';
|
|
234
|
+
case 'hydrating':
|
|
235
|
+
return 'Hydrating remote session...';
|
|
236
|
+
case 'replaying':
|
|
237
|
+
return 'Replaying remote history...';
|
|
238
|
+
case 'resuming':
|
|
239
|
+
return 'Resuming remote sandbox...';
|
|
240
|
+
case 'reconnecting':
|
|
241
|
+
return 'Connection lost - reconnecting...';
|
|
242
|
+
case 'paused':
|
|
243
|
+
case 'disconnected':
|
|
244
|
+
case 'live':
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function clearRemoteLifecycleWorkingMessage(
|
|
250
|
+
ui: RemoteLifecycleWorkingMessageUi,
|
|
251
|
+
lifecycleOwnsWorkingMessage: boolean
|
|
252
|
+
): boolean {
|
|
253
|
+
if (lifecycleOwnsWorkingMessage) {
|
|
254
|
+
ui.setWorkingMessage();
|
|
255
|
+
}
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function syncRemoteLifecycleWorkingMessage(
|
|
260
|
+
state: RemoteLifecycleState,
|
|
261
|
+
ui: RemoteLifecycleWorkingMessageUi,
|
|
262
|
+
lifecycleOwnsWorkingMessage: boolean
|
|
263
|
+
): boolean {
|
|
264
|
+
const working = getRemoteLifecycleWorkingMessage(state);
|
|
265
|
+
if (working) {
|
|
266
|
+
ui.setWorkingMessage(working);
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
return clearRemoteLifecycleWorkingMessage(ui, lifecycleOwnsWorkingMessage);
|
|
270
|
+
}
|