@robota-sdk/agent-transport-ws 3.0.0-beta.62 → 3.0.0-beta.76
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 +5 -88
- package/dist/node/index.cjs +1 -299
- package/dist/node/index.d.ts +144 -117
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +2 -271
- package/dist/node/index.js.map +1 -0
- package/package.json +21 -13
- package/src/__tests__/ws-handler.test.ts +409 -0
- package/src/__tests__/ws-transport.test.ts +53 -0
- package/src/index.ts +13 -0
- package/src/ws-background-messages.ts +170 -0
- package/src/ws-handler.ts +280 -0
- package/src/ws-protocol.ts +78 -0
- package/src/ws-transport-configurable.ts +128 -0
- package/src/ws-transport.ts +42 -0
- package/dist/node/index.d.cts +0 -186
package/dist/node/index.d.ts
CHANGED
|
@@ -1,152 +1,151 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IBackgroundTaskInput, IBackgroundTaskListFilter, IBackgroundTaskLogCursor, IBackgroundTaskLogPage, IBackgroundTaskState, IExecutionWorkspaceEntry, IExecutionWorkspaceSnapshot, InteractiveSession, TBackgroundTaskEvent, TExecutionAttention, TExecutionWorkspaceStatus } from "@robota-sdk/agent-framework";
|
|
2
|
+
import { IBackgroundJobGroupState, ICommandResult, IConfigurableTransport, IExecutionResult, IExecutionWorkspaceSnapshot as IExecutionWorkspaceSnapshot$1, IInteractiveSession, IToolState, ITransportAdapter, TBackgroundJobGroupEvent } from "@robota-sdk/agent-interface-transport";
|
|
3
|
+
import { TUniversalValue } from "@robota-sdk/agent-core";
|
|
2
4
|
|
|
5
|
+
//#region src/ws-protocol.d.ts
|
|
3
6
|
type TBackgroundControlAction = 'cancel' | 'close' | 'send';
|
|
4
7
|
/** Inbound message from client to server. */
|
|
5
8
|
type TClientMessage = {
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
type: 'submit';
|
|
10
|
+
prompt: string;
|
|
8
11
|
} | {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
type: 'command';
|
|
13
|
+
name: string;
|
|
14
|
+
args?: string;
|
|
12
15
|
} | {
|
|
13
|
-
|
|
16
|
+
type: 'abort';
|
|
14
17
|
} | {
|
|
15
|
-
|
|
18
|
+
type: 'cancel-queue';
|
|
16
19
|
} | {
|
|
17
|
-
|
|
20
|
+
type: 'get-messages';
|
|
18
21
|
} | {
|
|
19
|
-
|
|
22
|
+
type: 'get-context';
|
|
20
23
|
} | {
|
|
21
|
-
|
|
24
|
+
type: 'get-executing';
|
|
22
25
|
} | {
|
|
23
|
-
|
|
26
|
+
type: 'get-pending';
|
|
24
27
|
} | {
|
|
25
|
-
|
|
26
|
-
filter?: IBackgroundTaskListFilter;
|
|
28
|
+
type: 'get-execution-workspace';
|
|
27
29
|
} | {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
type: 'get-background-tasks';
|
|
31
|
+
filter?: IBackgroundTaskListFilter;
|
|
30
32
|
} | {
|
|
31
|
-
|
|
33
|
+
type: 'get-background-task';
|
|
34
|
+
taskId: string;
|
|
32
35
|
} | {
|
|
33
|
-
|
|
34
|
-
groupId: string;
|
|
36
|
+
type: 'get-background-job-groups';
|
|
35
37
|
} | {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
type: 'get-background-job-group';
|
|
39
|
+
groupId: string;
|
|
38
40
|
} | {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
reason?: string;
|
|
41
|
+
type: 'wait-background-job-group';
|
|
42
|
+
groupId: string;
|
|
42
43
|
} | {
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
type: 'cancel-background-task';
|
|
45
|
+
taskId: string;
|
|
46
|
+
reason?: string;
|
|
45
47
|
} | {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
input: IBackgroundTaskInput;
|
|
48
|
+
type: 'close-background-task';
|
|
49
|
+
taskId: string;
|
|
49
50
|
} | {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
type: 'send-background-task';
|
|
52
|
+
taskId: string;
|
|
53
|
+
input: IBackgroundTaskInput;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'read-background-task-log';
|
|
56
|
+
taskId: string;
|
|
57
|
+
cursor?: IBackgroundTaskLogCursor;
|
|
53
58
|
};
|
|
54
59
|
/** Outbound message from server to client. */
|
|
55
60
|
type TServerMessage = {
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
type: 'text_delta';
|
|
62
|
+
delta: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: 'user_message';
|
|
65
|
+
content: string;
|
|
58
66
|
} | {
|
|
59
|
-
|
|
60
|
-
|
|
67
|
+
type: 'tool_start';
|
|
68
|
+
state: IToolState;
|
|
61
69
|
} | {
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
type: 'tool_end';
|
|
71
|
+
state: IToolState;
|
|
64
72
|
} | {
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
type: 'thinking';
|
|
74
|
+
isThinking: boolean;
|
|
67
75
|
} | {
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
type: 'complete';
|
|
77
|
+
result: IExecutionResult;
|
|
70
78
|
} | {
|
|
71
|
-
|
|
72
|
-
|
|
79
|
+
type: 'interrupted';
|
|
80
|
+
result: IExecutionResult;
|
|
73
81
|
} | {
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
type: 'error';
|
|
83
|
+
message: string;
|
|
76
84
|
} | {
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
type: 'command_result';
|
|
86
|
+
name: string;
|
|
87
|
+
message: string;
|
|
88
|
+
success: boolean;
|
|
89
|
+
data?: ICommandResult['data'];
|
|
79
90
|
} | {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
message: string;
|
|
83
|
-
success: boolean;
|
|
84
|
-
data?: ICommandResult['data'];
|
|
91
|
+
type: 'messages';
|
|
92
|
+
messages: ReturnType<InteractiveSession['getMessages']>;
|
|
85
93
|
} | {
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
type: 'context';
|
|
95
|
+
state: ReturnType<InteractiveSession['getContextState']>;
|
|
88
96
|
} | {
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
type: 'executing';
|
|
98
|
+
executing: boolean;
|
|
91
99
|
} | {
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
type: 'pending';
|
|
101
|
+
pending: string | null;
|
|
94
102
|
} | {
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
type: 'execution_workspace_event';
|
|
104
|
+
snapshot: IExecutionWorkspaceSnapshot$1;
|
|
97
105
|
} | {
|
|
98
|
-
|
|
99
|
-
|
|
106
|
+
type: 'background_task_event';
|
|
107
|
+
event: TBackgroundTaskEvent;
|
|
100
108
|
} | {
|
|
101
|
-
|
|
102
|
-
|
|
109
|
+
type: 'background_job_group_event';
|
|
110
|
+
event: TBackgroundJobGroupEvent;
|
|
103
111
|
} | {
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
type: 'background_tasks';
|
|
113
|
+
tasks: IBackgroundTaskState[];
|
|
106
114
|
} | {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
115
|
+
type: 'background_task';
|
|
116
|
+
taskId: string;
|
|
117
|
+
task: IBackgroundTaskState | null;
|
|
110
118
|
} | {
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
type: 'background_job_groups';
|
|
120
|
+
groups: IBackgroundJobGroupState[];
|
|
113
121
|
} | {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
type: 'background_job_group';
|
|
123
|
+
groupId: string;
|
|
124
|
+
group: IBackgroundJobGroupState | null;
|
|
117
125
|
} | {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
126
|
+
type: 'background_task_log';
|
|
127
|
+
taskId: string;
|
|
128
|
+
page: IBackgroundTaskLogPage;
|
|
121
129
|
} | {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
type: 'background_task_control_result';
|
|
131
|
+
action: TBackgroundControlAction;
|
|
132
|
+
taskId: string;
|
|
133
|
+
success: boolean;
|
|
134
|
+
message?: string;
|
|
127
135
|
} | {
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
type: 'protocol_error';
|
|
137
|
+
message: string;
|
|
130
138
|
};
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
* WebSocket transport adapter — exposes InteractiveSession over WebSocket.
|
|
134
|
-
*
|
|
135
|
-
* Framework-agnostic: works with any WebSocket implementation via
|
|
136
|
-
* send/onMessage callbacks. No dependency on ws, uWebSockets, etc.
|
|
137
|
-
*
|
|
138
|
-
* Protocol: JSON messages with { type, ...payload } structure.
|
|
139
|
-
* Server pushes InteractiveSession events to client in real-time.
|
|
140
|
-
*/
|
|
141
|
-
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/ws-handler.d.ts
|
|
142
141
|
interface IWsHandlerOptions {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
/** IInteractiveSession to expose. */
|
|
143
|
+
session: IInteractiveSession;
|
|
144
|
+
/** Send a JSON message to the client. */
|
|
145
|
+
send: (message: TServerMessage) => void;
|
|
147
146
|
}
|
|
148
147
|
/**
|
|
149
|
-
* Create a WebSocket message handler for an
|
|
148
|
+
* Create a WebSocket message handler for an IInteractiveSession.
|
|
150
149
|
*
|
|
151
150
|
* Returns:
|
|
152
151
|
* - `onMessage(data)`: call this when the WebSocket receives a message
|
|
@@ -164,23 +163,51 @@ interface IWsHandlerOptions {
|
|
|
164
163
|
* ```
|
|
165
164
|
*/
|
|
166
165
|
declare function createWsHandler(options: IWsHandlerOptions): {
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
onMessage: (data: string) => void;
|
|
167
|
+
cleanup: () => void;
|
|
169
168
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
* ITransportAdapter implementation for WebSocket transport.
|
|
173
|
-
*
|
|
174
|
-
* Wraps createWsHandler into the unified ITransportAdapter interface.
|
|
175
|
-
* After start(), the consumer must wire onMessage to their WebSocket.
|
|
176
|
-
*/
|
|
177
|
-
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/ws-transport.d.ts
|
|
178
171
|
interface IWsTransportOptions {
|
|
179
|
-
|
|
180
|
-
|
|
172
|
+
/** Send a JSON message to the connected WebSocket client. */
|
|
173
|
+
send: (message: TServerMessage) => void;
|
|
181
174
|
}
|
|
182
|
-
declare function createWsTransport(options: IWsTransportOptions): ITransportAdapter & {
|
|
183
|
-
|
|
175
|
+
declare function createWsTransport(options: IWsTransportOptions): ITransportAdapter<IInteractiveSession> & {
|
|
176
|
+
onMessage: ((data: string) => void) | null;
|
|
184
177
|
};
|
|
185
|
-
|
|
186
|
-
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/ws-transport-configurable.d.ts
|
|
180
|
+
interface IWsTransportConfig {
|
|
181
|
+
port?: number;
|
|
182
|
+
maxRetries?: number;
|
|
183
|
+
}
|
|
184
|
+
declare class WsTransport implements IConfigurableTransport<IInteractiveSession> {
|
|
185
|
+
readonly name = "ws";
|
|
186
|
+
readonly defaultEnabled = true;
|
|
187
|
+
readonly optionsSchema: {
|
|
188
|
+
port: {
|
|
189
|
+
type: string;
|
|
190
|
+
description: string;
|
|
191
|
+
default: number;
|
|
192
|
+
};
|
|
193
|
+
maxRetries: {
|
|
194
|
+
type: string;
|
|
195
|
+
description: string;
|
|
196
|
+
default: number;
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
private session;
|
|
200
|
+
private stopFn;
|
|
201
|
+
private readonly port;
|
|
202
|
+
private readonly maxRetries;
|
|
203
|
+
constructor(config?: IWsTransportConfig);
|
|
204
|
+
attach(session: IInteractiveSession): void;
|
|
205
|
+
start(): Promise<void>;
|
|
206
|
+
stop(): Promise<void>;
|
|
207
|
+
validateOptions(options: Record<string, TUniversalValue>): boolean;
|
|
208
|
+
private bindWithRetry;
|
|
209
|
+
private tryBind;
|
|
210
|
+
}
|
|
211
|
+
//#endregion
|
|
212
|
+
export { type IExecutionWorkspaceEntry, type IExecutionWorkspaceSnapshot, type IWsHandlerOptions, type IWsTransportConfig, type IWsTransportOptions, type TClientMessage, type TExecutionAttention, type TExecutionWorkspaceStatus, type TServerMessage, WsTransport, createWsHandler, createWsTransport };
|
|
213
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/ws-protocol.ts","../../src/ws-handler.ts","../../src/ws-transport.ts","../../src/ws-transport-configurable.ts"],"mappings":";;;;;KAkBY,wBAAA;;KAGA,cAAA;EACN,IAAA;EAAgB,MAAA;AAAA;EAChB,IAAA;EAAiB,IAAA;EAAc,IAAA;AAAA;EAC/B,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAA8B,MAAA,GAAS,yBAAA;AAAA;EACvC,IAAA;EAA6B,MAAA;AAAA;EAC7B,IAAA;AAAA;EACA,IAAA;EAAkC,OAAA;AAAA;EAClC,IAAA;EAAmC,OAAA;AAAA;EACnC,IAAA;EAAgC,MAAA;EAAgB,MAAA;AAAA;EAChD,IAAA;EAA+B,MAAA;AAAA;EAC/B,IAAA;EAA8B,MAAA;EAAgB,KAAA,EAAO,oBAAA;AAAA;EACrD,IAAA;EAAkC,MAAA;EAAgB,MAAA,GAAS,wBAAA;AAAA;AAGjE;AAAA,KAAY,cAAA;EACN,IAAA;EAAoB,KAAA;AAAA;EACpB,IAAA;EAAsB,OAAA;AAAA;EACtB,IAAA;EAAoB,KAAA,EAAO,UAAA;AAAA;EAC3B,IAAA;EAAkB,KAAA,EAAO,UAAA;AAAA;EACzB,IAAA;EAAkB,UAAA;AAAA;EAClB,IAAA;EAAkB,MAAA,EAAQ,gBAAA;AAAA;EAC1B,IAAA;EAAqB,MAAA,EAAQ,gBAAA;AAAA;EAC7B,IAAA;EAAe,OAAA;AAAA;EAEf,IAAA;EACA,IAAA;EACA,OAAA;EACA,OAAA;EACA,IAAA,GAAO,cAAA;AAAA;EAEP,IAAA;EAAkB,QAAA,EAAU,UAAA,CAAW,kBAAA;AAAA;EACvC,IAAA;EAAiB,KAAA,EAAO,UAAA,CAAW,kBAAA;AAAA;EACnC,IAAA;EAAmB,SAAA;AAAA;EACnB,IAAA;EAAiB,OAAA;AAAA;EACjB,IAAA;EAAmC,QAAA,EAAU,6BAAA;AAAA;EAC7C,IAAA;EAA+B,KAAA,EAAO,oBAAA;AAAA;EACtC,IAAA;EAAoC,KAAA,EAAO,wBAAA;AAAA;EAC3C,IAAA;EAA0B,KAAA,EAAO,oBAAA;AAAA;EACjC,IAAA;EAAyB,MAAA;EAAgB,IAAA,EAAM,oBAAA;AAAA;EAC/C,IAAA;EAA+B,MAAA,EAAQ,wBAAA;AAAA;EACvC,IAAA;EAA8B,OAAA;EAAiB,KAAA,EAAO,wBAAA;AAAA;EACtD,IAAA;EAA6B,MAAA;EAAgB,IAAA,EAAM,sBAAA;AAAA;EAEnD,IAAA;EACA,MAAA,EAAQ,wBAAA;EACR,MAAA;EACA,OAAA;EACA,OAAA;AAAA;EAEA,IAAA;EAAwB,OAAA;AAAA;;;UCpDb,iBAAA;;EAEf,OAAA,EAAS,mBAAA;EDWgD;ECTzD,IAAA,GAAO,OAAA,EAAS,cAAc;AAAA;;;;;;;;;;;;;;;;;;;iBAqBhB,eAAA,CAAgB,OAAA,EAAS,iBAAiB;EACxD,SAAA,GAAY,IAAA;EACZ,OAAA;AAAA;;;UCxCe,mBAAA;EFMmB;EEJlC,IAAA,GAAO,OAAA,EAAS,cAAc;AAAA;AAAA,iBAGhB,iBAAA,CACd,OAAA,EAAS,mBAAA,GACR,iBAAA,CAAkB,mBAAA;EAAyB,SAAA,IAAa,IAAA;AAAA;;;UCE1C,kBAAA;EACf,IAAA;EACA,UAAU;AAAA;AAAA,cAGC,WAAA,YAAuB,sBAAA,CAAuB,mBAAA;EAAA,SAChD,IAAA;EAAA,SACA,cAAA;EAAA,SACA,aAAA;;;;;;;;;;;;UASD,OAAA;EAAA,QACA,MAAA;EAAA,iBACS,IAAA;EAAA,iBACA,UAAA;cAEL,MAAA,GAAQ,kBAAA;EAKpB,MAAA,CAAO,OAAA,EAAS,mBAAA;EAIV,KAAA,IAAS,OAAA;EAMT,IAAA,IAAQ,OAAA;EAKd,eAAA,CAAgB,OAAA,EAAS,MAAA,SAAe,eAAA;EAAA,QAQhC,aAAA;EAAA,QAYA,OAAA;AAAA"}
|
package/dist/node/index.js
CHANGED
|
@@ -1,271 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (msg.type === "get-background-tasks") {
|
|
4
|
-
send({ type: "background_tasks", tasks: session.listBackgroundTasks(msg.filter) });
|
|
5
|
-
return;
|
|
6
|
-
}
|
|
7
|
-
if (msg.type === "get-background-task") {
|
|
8
|
-
sendBackgroundTaskSnapshot(session, send, msg);
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
if (msg.type === "get-background-job-groups") {
|
|
12
|
-
send({ type: "background_job_groups", groups: session.listBackgroundJobGroups() });
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
if (msg.type === "get-background-job-group") {
|
|
16
|
-
sendBackgroundJobGroupSnapshot(session, send, msg);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (msg.type === "wait-background-job-group") {
|
|
20
|
-
sendBackgroundJobGroupWaitResult(session, send, msg);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
sendBackgroundTaskLogPage(session, send, msg);
|
|
24
|
-
}
|
|
25
|
-
function handleBackgroundControlMessage(session, send, msg) {
|
|
26
|
-
if (!msg.taskId) {
|
|
27
|
-
send({ type: "protocol_error", message: "taskId is required" });
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
if (msg.type === "cancel-background-task") {
|
|
31
|
-
sendBackgroundTaskControlResult(
|
|
32
|
-
send,
|
|
33
|
-
"cancel",
|
|
34
|
-
msg.taskId,
|
|
35
|
-
session.cancelBackgroundTask(msg.taskId, msg.reason)
|
|
36
|
-
);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (msg.type === "close-background-task") {
|
|
40
|
-
sendBackgroundTaskControlResult(
|
|
41
|
-
send,
|
|
42
|
-
"close",
|
|
43
|
-
msg.taskId,
|
|
44
|
-
session.closeBackgroundTask(msg.taskId)
|
|
45
|
-
);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
sendBackgroundTaskInput(session, send, msg);
|
|
49
|
-
}
|
|
50
|
-
function sendBackgroundTaskSnapshot(session, send, msg) {
|
|
51
|
-
if (!msg.taskId) {
|
|
52
|
-
send({ type: "protocol_error", message: "taskId is required" });
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
send({
|
|
56
|
-
type: "background_task",
|
|
57
|
-
taskId: msg.taskId,
|
|
58
|
-
task: session.getBackgroundTask(msg.taskId) ?? null
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
function sendBackgroundTaskLogPage(session, send, msg) {
|
|
62
|
-
if (!msg.taskId) {
|
|
63
|
-
send({ type: "protocol_error", message: "taskId is required" });
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
session.readBackgroundTaskLog(msg.taskId, msg.cursor).then(
|
|
67
|
-
(page) => send({ type: "background_task_log", taskId: msg.taskId, page }),
|
|
68
|
-
(error) => send({ type: "protocol_error", message: error.message })
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
function sendBackgroundJobGroupSnapshot(session, send, msg) {
|
|
72
|
-
if (!msg.groupId) {
|
|
73
|
-
send({ type: "protocol_error", message: "groupId is required" });
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
send({
|
|
77
|
-
type: "background_job_group",
|
|
78
|
-
groupId: msg.groupId,
|
|
79
|
-
group: session.getBackgroundJobGroup(msg.groupId) ?? null
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
function sendBackgroundJobGroupWaitResult(session, send, msg) {
|
|
83
|
-
if (!msg.groupId) {
|
|
84
|
-
send({ type: "protocol_error", message: "groupId is required" });
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
session.waitBackgroundJobGroup(msg.groupId).then(
|
|
88
|
-
(group) => send({ type: "background_job_group", groupId: msg.groupId, group }),
|
|
89
|
-
(error) => send({ type: "protocol_error", message: error.message })
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
function sendBackgroundTaskInput(session, send, msg) {
|
|
93
|
-
if (!msg.input) {
|
|
94
|
-
send({ type: "protocol_error", message: "input is required" });
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
sendBackgroundTaskControlResult(
|
|
98
|
-
send,
|
|
99
|
-
"send",
|
|
100
|
-
msg.taskId,
|
|
101
|
-
session.sendBackgroundTask(msg.taskId, msg.input)
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
function sendBackgroundTaskControlResult(send, action, taskId, operation) {
|
|
105
|
-
operation.then(
|
|
106
|
-
() => send({ type: "background_task_control_result", action, taskId, success: true }),
|
|
107
|
-
(error) => send({
|
|
108
|
-
type: "background_task_control_result",
|
|
109
|
-
action,
|
|
110
|
-
taskId,
|
|
111
|
-
success: false,
|
|
112
|
-
message: error.message
|
|
113
|
-
})
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// src/ws-handler.ts
|
|
118
|
-
function createWsHandler(options) {
|
|
119
|
-
const cleanup = subscribeSessionEvents(options.session, options.send);
|
|
120
|
-
const onMessage = createWsMessageHandler(options.session, options.send);
|
|
121
|
-
return { onMessage, cleanup };
|
|
122
|
-
}
|
|
123
|
-
function subscribeSessionEvents(session, send) {
|
|
124
|
-
const onUserMessage = (content) => send({ type: "user_message", content });
|
|
125
|
-
const onTextDelta = (delta) => send({ type: "text_delta", delta });
|
|
126
|
-
const onToolStart = (state) => send({ type: "tool_start", state });
|
|
127
|
-
const onToolEnd = (state) => send({ type: "tool_end", state });
|
|
128
|
-
const onThinking = (isThinking) => send({ type: "thinking", isThinking });
|
|
129
|
-
const onComplete = (result) => send({ type: "complete", result });
|
|
130
|
-
const onInterrupted = (result) => send({ type: "interrupted", result });
|
|
131
|
-
const onError = (error) => send({ type: "error", message: error.message });
|
|
132
|
-
const onBackgroundTaskEvent = (event) => send({ type: "background_task_event", event });
|
|
133
|
-
const onBackgroundJobGroupEvent = (event) => send({ type: "background_job_group_event", event });
|
|
134
|
-
session.on("user_message", onUserMessage);
|
|
135
|
-
session.on("text_delta", onTextDelta);
|
|
136
|
-
session.on("tool_start", onToolStart);
|
|
137
|
-
session.on("tool_end", onToolEnd);
|
|
138
|
-
session.on("thinking", onThinking);
|
|
139
|
-
session.on("complete", onComplete);
|
|
140
|
-
session.on("interrupted", onInterrupted);
|
|
141
|
-
session.on("error", onError);
|
|
142
|
-
session.on("background_task_event", onBackgroundTaskEvent);
|
|
143
|
-
session.on("background_job_group_event", onBackgroundJobGroupEvent);
|
|
144
|
-
return () => {
|
|
145
|
-
session.off("user_message", onUserMessage);
|
|
146
|
-
session.off("text_delta", onTextDelta);
|
|
147
|
-
session.off("tool_start", onToolStart);
|
|
148
|
-
session.off("tool_end", onToolEnd);
|
|
149
|
-
session.off("thinking", onThinking);
|
|
150
|
-
session.off("complete", onComplete);
|
|
151
|
-
session.off("interrupted", onInterrupted);
|
|
152
|
-
session.off("error", onError);
|
|
153
|
-
session.off("background_task_event", onBackgroundTaskEvent);
|
|
154
|
-
session.off("background_job_group_event", onBackgroundJobGroupEvent);
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
function createWsMessageHandler(session, send) {
|
|
158
|
-
return (data) => {
|
|
159
|
-
const msg = parseClientMessage(data, send);
|
|
160
|
-
if (!msg) return;
|
|
161
|
-
handleClientMessage(session, send, msg);
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function parseClientMessage(data, send) {
|
|
165
|
-
try {
|
|
166
|
-
return JSON.parse(data);
|
|
167
|
-
} catch {
|
|
168
|
-
send({ type: "protocol_error", message: "Invalid JSON" });
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
function handleClientMessage(session, send, msg) {
|
|
173
|
-
if (isSessionControlMessage(msg)) {
|
|
174
|
-
handleSessionControlMessage(session, send, msg);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
if (isSessionQueryMessage(msg)) {
|
|
178
|
-
handleSessionQueryMessage(session, send, msg);
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
if (isBackgroundQueryMessage(msg)) {
|
|
182
|
-
handleBackgroundQueryMessage(session, send, msg);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
if (isBackgroundControlMessage(msg)) {
|
|
186
|
-
handleBackgroundControlMessage(session, send, msg);
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
send({ type: "protocol_error", message: `Unknown message type: ${getMessageType(msg)}` });
|
|
190
|
-
}
|
|
191
|
-
function getMessageType(msg) {
|
|
192
|
-
return msg.type;
|
|
193
|
-
}
|
|
194
|
-
function isSessionControlMessage(msg) {
|
|
195
|
-
return msg.type === "submit" || msg.type === "command" || msg.type === "abort" || msg.type === "cancel-queue";
|
|
196
|
-
}
|
|
197
|
-
function isSessionQueryMessage(msg) {
|
|
198
|
-
return msg.type === "get-messages" || msg.type === "get-context" || msg.type === "get-executing" || msg.type === "get-pending";
|
|
199
|
-
}
|
|
200
|
-
function isBackgroundQueryMessage(msg) {
|
|
201
|
-
return msg.type === "get-background-tasks" || msg.type === "get-background-task" || msg.type === "read-background-task-log" || msg.type === "get-background-job-groups" || msg.type === "get-background-job-group" || msg.type === "wait-background-job-group";
|
|
202
|
-
}
|
|
203
|
-
function isBackgroundControlMessage(msg) {
|
|
204
|
-
return msg.type === "cancel-background-task" || msg.type === "close-background-task" || msg.type === "send-background-task";
|
|
205
|
-
}
|
|
206
|
-
function handleSessionControlMessage(session, send, msg) {
|
|
207
|
-
if (msg.type === "submit") {
|
|
208
|
-
if (!msg.prompt) {
|
|
209
|
-
send({ type: "protocol_error", message: "prompt is required" });
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
session.submit(msg.prompt);
|
|
213
|
-
} else if (msg.type === "command") {
|
|
214
|
-
if (!msg.name) {
|
|
215
|
-
send({ type: "protocol_error", message: "name is required" });
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
session.executeCommand(msg.name, msg.args ?? "").then((result) => {
|
|
219
|
-
send({
|
|
220
|
-
type: "command_result",
|
|
221
|
-
name: msg.name,
|
|
222
|
-
message: result?.message ?? `Unknown command: ${msg.name}`,
|
|
223
|
-
success: result?.success ?? false,
|
|
224
|
-
data: result?.data
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
} else if (msg.type === "abort") {
|
|
228
|
-
session.abort();
|
|
229
|
-
} else {
|
|
230
|
-
session.cancelQueue();
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
function handleSessionQueryMessage(session, send, msg) {
|
|
234
|
-
if (msg.type === "get-messages") {
|
|
235
|
-
send({ type: "messages", messages: session.getMessages() });
|
|
236
|
-
} else if (msg.type === "get-context") {
|
|
237
|
-
send({ type: "context", state: session.getContextState() });
|
|
238
|
-
} else if (msg.type === "get-executing") {
|
|
239
|
-
send({ type: "executing", executing: session.isExecuting() });
|
|
240
|
-
} else {
|
|
241
|
-
send({ type: "pending", pending: session.getPendingPrompt() });
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// src/ws-transport.ts
|
|
246
|
-
function createWsTransport(options) {
|
|
247
|
-
let session = null;
|
|
248
|
-
let cleanup = null;
|
|
249
|
-
return {
|
|
250
|
-
name: "ws",
|
|
251
|
-
onMessage: null,
|
|
252
|
-
attach(s) {
|
|
253
|
-
session = s;
|
|
254
|
-
},
|
|
255
|
-
async start() {
|
|
256
|
-
if (!session) throw new Error("No session attached. Call attach() first.");
|
|
257
|
-
const handler = createWsHandler({ session, send: options.send });
|
|
258
|
-
cleanup = handler.cleanup;
|
|
259
|
-
this.onMessage = handler.onMessage;
|
|
260
|
-
},
|
|
261
|
-
async stop() {
|
|
262
|
-
cleanup?.();
|
|
263
|
-
cleanup = null;
|
|
264
|
-
this.onMessage = null;
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
export {
|
|
269
|
-
createWsHandler,
|
|
270
|
-
createWsTransport
|
|
271
|
-
};
|
|
1
|
+
import{createServer as e}from"node:http";import{WebSocket as t,WebSocketServer as n}from"ws";function r(e,t,n){if(n.type===`get-background-tasks`){t({type:`background_tasks`,tasks:e.listBackgroundTasks(n.filter)});return}if(n.type===`get-background-task`){a(e,t,n);return}if(n.type===`get-background-job-groups`){t({type:`background_job_groups`,groups:e.listBackgroundJobGroups()});return}if(n.type===`get-background-job-group`){s(e,t,n);return}if(n.type===`wait-background-job-group`){c(e,t,n);return}o(e,t,n)}function i(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}if(n.type===`cancel-background-task`){u(t,`cancel`,n.taskId,e.cancelBackgroundTask(n.taskId,n.reason));return}if(n.type===`close-background-task`){u(t,`close`,n.taskId,e.closeBackgroundTask(n.taskId));return}l(e,t,n)}function a(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}t({type:`background_task`,taskId:n.taskId,task:e.getBackgroundTask(n.taskId)??null})}function o(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}e.readBackgroundTaskLog(n.taskId,n.cursor).then(e=>t({type:`background_task_log`,taskId:n.taskId,page:e}),e=>t({type:`protocol_error`,message:e.message}))}function s(e,t,n){if(!n.groupId){t({type:`protocol_error`,message:`groupId is required`});return}t({type:`background_job_group`,groupId:n.groupId,group:e.getBackgroundJobGroup(n.groupId)??null})}function c(e,t,n){if(!n.groupId){t({type:`protocol_error`,message:`groupId is required`});return}e.waitBackgroundJobGroup(n.groupId).then(e=>t({type:`background_job_group`,groupId:n.groupId,group:e}),e=>t({type:`protocol_error`,message:e.message}))}function l(e,t,n){if(!n.input){t({type:`protocol_error`,message:`input is required`});return}u(t,`send`,n.taskId,e.sendBackgroundTask(n.taskId,n.input))}function u(e,t,n,r){r.then(()=>e({type:`background_task_control_result`,action:t,taskId:n,success:!0}),r=>e({type:`background_task_control_result`,action:t,taskId:n,success:!1,message:r.message}))}function d(e){let t=f(e.session,e.send);return{onMessage:p(e.session,e.send),cleanup:t}}function f(e,t){let n=e=>t({type:`user_message`,content:e}),r=e=>t({type:`text_delta`,delta:e}),i=e=>t({type:`tool_start`,state:e}),a=e=>t({type:`tool_end`,state:e}),o=e=>t({type:`thinking`,isThinking:e}),s=e=>t({type:`complete`,result:e}),c=e=>t({type:`interrupted`,result:e}),l=e=>t({type:`error`,message:e.message}),u=e=>t({type:`background_task_event`,event:e}),d=e=>t({type:`background_job_group_event`,event:e}),f=e=>t({type:`execution_workspace_event`,snapshot:e.snapshot});return e.on(`user_message`,n),e.on(`text_delta`,r),e.on(`tool_start`,i),e.on(`tool_end`,a),e.on(`thinking`,o),e.on(`complete`,s),e.on(`interrupted`,c),e.on(`error`,l),e.on(`background_task_event`,u),e.on(`background_job_group_event`,d),e.on(`execution_workspace_event`,f),()=>{e.off(`user_message`,n),e.off(`text_delta`,r),e.off(`tool_start`,i),e.off(`tool_end`,a),e.off(`thinking`,o),e.off(`complete`,s),e.off(`interrupted`,c),e.off(`error`,l),e.off(`background_task_event`,u),e.off(`background_job_group_event`,d),e.off(`execution_workspace_event`,f)}}function p(e,t){return n=>{let r=m(n,t);r&&h(e,t,r)}}function m(e,t){try{return JSON.parse(e)}catch{return t({type:`protocol_error`,message:`Invalid JSON`}),null}}function h(e,t,n){if(_(n)){x(e,t,n);return}if(v(n)){S(e,t,n);return}if(y(n)){r(e,t,n);return}if(b(n)){i(e,t,n);return}t({type:`protocol_error`,message:`Unknown message type: ${g(n)}`})}function g(e){return e.type}function _(e){return e.type===`submit`||e.type===`command`||e.type===`abort`||e.type===`cancel-queue`}function v(e){return e.type===`get-messages`||e.type===`get-context`||e.type===`get-executing`||e.type===`get-pending`||e.type===`get-execution-workspace`}function y(e){return e.type===`get-background-tasks`||e.type===`get-background-task`||e.type===`read-background-task-log`||e.type===`get-background-job-groups`||e.type===`get-background-job-group`||e.type===`wait-background-job-group`}function b(e){return e.type===`cancel-background-task`||e.type===`close-background-task`||e.type===`send-background-task`}function x(e,t,n){if(n.type===`submit`){if(!n.prompt){t({type:`protocol_error`,message:`prompt is required`});return}e.submit(n.prompt)}else if(n.type===`command`){if(!n.name){t({type:`protocol_error`,message:`name is required`});return}e.executeCommand(n.name,n.args??``).then(e=>{t({type:`command_result`,name:n.name,message:e?.message??`Unknown command: ${n.name}`,success:e?.success??!1,data:e?.data})})}else n.type===`abort`?e.abort():e.cancelQueue()}function S(e,t,n){n.type===`get-messages`?t({type:`messages`,messages:e.getMessages()}):n.type===`get-context`?t({type:`context`,state:e.getContextState()}):n.type===`get-executing`?t({type:`executing`,executing:e.isExecuting()}):n.type===`get-execution-workspace`?t({type:`execution_workspace_event`,snapshot:e.getExecutionWorkspaceSnapshot()}):t({type:`pending`,pending:e.getPendingPrompt()})}function C(e){let t=null,n=null;return{name:`ws`,onMessage:null,attach(e){t=e},async start(){if(!t)throw Error(`No session attached. Call attach() first.`);let r=d({session:t,send:e.send});n=r.cleanup,this.onMessage=r.onMessage},async stop(){n?.(),n=null,this.onMessage=null}}}const w=7070;var T=class{name=`ws`;defaultEnabled=!0;optionsSchema={port:{type:`number`,description:`WebSocket server port`,default:w},maxRetries:{type:`number`,description:`Port retry attempts when port is occupied`,default:20}};session=null;stopFn=null;port;maxRetries;constructor(e={}){this.port=e.port??w,this.maxRetries=e.maxRetries??20}attach(e){this.session=e}async start(){if(!this.session)throw Error(`WsTransport: attach() must be called before start()`);let e=await this.bindWithRetry(this.session,this.port,this.maxRetries);this.stopFn=e.stop}async stop(){await this.stopFn?.(),this.stopFn=null}validateOptions(e){let{port:t,maxRetries:n}=e;return!(t!==void 0&&(typeof t!=`number`||t<1||t>65535)||n!==void 0&&(typeof n!=`number`||n<0))}bindWithRetry(e,t,n){return this.tryBind(e,t).catch(r=>{if(r.code===`EADDRINUSE`&&n>0)return this.bindWithRetry(e,t+1,n-1);throw r})}tryBind(r,i){return new Promise((a,o)=>{let s=e((e,t)=>{t.writeHead(400).end(`WebSocket endpoint`)});s.on(`error`,e=>{s.close(),o(e)}),s.listen(i,`127.0.0.1`,()=>{let e=new n({server:s});e.on(`connection`,e=>{let n=n=>{e.readyState===t.OPEN&&e.send(JSON.stringify(n))},{onMessage:i,cleanup:a}=d({session:r,send:n});e.on(`message`,e=>i(String(e))),e.on(`close`,a),e.on(`error`,a),n({type:`messages`,messages:r.getMessages()}),n({type:`execution_workspace_event`,snapshot:r.getExecutionWorkspaceSnapshot()})}),a({stop:()=>new Promise(t=>{e.close(()=>s.close(()=>t()))})})})})}};export{T as WsTransport,d as createWsHandler,C as createWsTransport};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|