@qilin-agent/client-connection 0.0.0-stage → 3.1.3
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/LICENSE +21 -0
- package/README.i18n.yaml +37 -0
- package/README.md +86 -2
- package/README.zh.md +87 -0
- package/lib/client.js +1459 -0
- package/lib/index.js +947 -0
- package/lib/types/api-path.d.ts +7 -0
- package/lib/types/api-request-trust.d.ts +38 -0
- package/lib/types/browser-auth.d.ts +68 -0
- package/lib/types/client/api.d.ts +14 -0
- package/lib/types/client/connection.d.ts +80 -0
- package/lib/types/client/index.d.ts +136 -0
- package/lib/types/client/random-uuid.d.ts +7 -0
- package/lib/types/client/rpc.d.ts +14 -0
- package/lib/types/http-bridge.d.ts +21 -0
- package/lib/types/index.d.ts +58 -0
- package/lib/types/loopback-hostname.d.ts +12 -0
- package/lib/types/operator-peer.d.ts +23 -0
- package/lib/types/recovery-config.d.ts +27 -0
- package/lib/types/rpc-host.d.ts +70 -0
- package/lib/types/rpc-schema.d.ts +30 -0
- package/lib/types/rpc.d.ts +262 -0
- package/lib/types/web-entry.d.ts +9 -0
- package/package.json +65 -3
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/** Generic unary RPC contracts shared by the Host and Client Connection halves. */
|
|
2
|
+
import type { Branded } from '@qilin-agent/brand';
|
|
3
|
+
import type { PeerScope } from '@qilin-agent/typert-protocol';
|
|
4
|
+
/** Correlation id minted by a caller and echoed by the Connection response. */
|
|
5
|
+
export type RpcId = Branded<'rpc-id'>;
|
|
6
|
+
/**
|
|
7
|
+
* Brand one validated string as a Connection correlation id.
|
|
8
|
+
* @param id - validated wire identity.
|
|
9
|
+
* @returns the same string with the correlation-id brand.
|
|
10
|
+
*/
|
|
11
|
+
export declare function RpcId(id: string): RpcId;
|
|
12
|
+
/** Carrier-neutral failure returned by one logical RPC endpoint. */
|
|
13
|
+
export interface ConnectionRpcFailure {
|
|
14
|
+
readonly code: string;
|
|
15
|
+
readonly message: string;
|
|
16
|
+
readonly details: object;
|
|
17
|
+
}
|
|
18
|
+
/** Carrier-neutral result returned by one logical RPC endpoint. */
|
|
19
|
+
export type ConnectionRpcResult<T> = {
|
|
20
|
+
readonly ok: true;
|
|
21
|
+
readonly value: T;
|
|
22
|
+
} | {
|
|
23
|
+
readonly ok: false;
|
|
24
|
+
readonly error: ConnectionRpcFailure;
|
|
25
|
+
};
|
|
26
|
+
/** Historical short name for a generic Connection result. */
|
|
27
|
+
export type RpcResult<T> = ConnectionRpcResult<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Convert a rejected transport operation into a generic failure result.
|
|
30
|
+
* @param error - rejected transport value.
|
|
31
|
+
* @returns an `internal` failure preserving the available message.
|
|
32
|
+
*/
|
|
33
|
+
export declare function transportError<T>(error: unknown): RpcResult<T>;
|
|
34
|
+
/** Narrow request form used by direct fixture adapters. */
|
|
35
|
+
export interface RpcRequest<P> {
|
|
36
|
+
readonly rpcId: RpcId;
|
|
37
|
+
readonly payload: P;
|
|
38
|
+
}
|
|
39
|
+
/** Narrow response form used by direct fixture adapters. */
|
|
40
|
+
export interface RpcResponse<T> {
|
|
41
|
+
readonly rpcId: RpcId;
|
|
42
|
+
readonly result: RpcResult<T>;
|
|
43
|
+
}
|
|
44
|
+
/** Full request envelope carried by Connection RPC transports. */
|
|
45
|
+
export interface ClientRequest {
|
|
46
|
+
readonly type: 'client-request';
|
|
47
|
+
readonly rpcId: RpcId;
|
|
48
|
+
readonly method: string;
|
|
49
|
+
readonly payload: unknown;
|
|
50
|
+
}
|
|
51
|
+
/** Full response envelope carried by Connection RPC transports. */
|
|
52
|
+
export interface ServerResponse {
|
|
53
|
+
readonly type: 'server-response';
|
|
54
|
+
readonly rpcId: RpcId;
|
|
55
|
+
readonly result: ConnectionRpcResult<unknown>;
|
|
56
|
+
}
|
|
57
|
+
/** Complete Connection RPC envelope union. */
|
|
58
|
+
export type RpcMessage = ClientRequest | ServerResponse;
|
|
59
|
+
/** HTTP request facts consumed by browser trust and authentication. */
|
|
60
|
+
export interface ConnectionTrustRequest {
|
|
61
|
+
/** Request headers supplied by either the Fetch or node:http representation. */
|
|
62
|
+
readonly headers: Headers | Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
63
|
+
/** Request method as received; node:http and Fetch callers always supply it. */
|
|
64
|
+
readonly method?: string | undefined;
|
|
65
|
+
/** Request target as received; node:http and Fetch callers always supply it. */
|
|
66
|
+
readonly url?: string | undefined;
|
|
67
|
+
}
|
|
68
|
+
/** HTTP status returned before dispatch, or undefined when the request may proceed. */
|
|
69
|
+
export type ConnectionRequestRejection = 401 | 403 | undefined;
|
|
70
|
+
/** Entry and configured-index request facts used by the browser-token exchange and the account-session gate. */
|
|
71
|
+
export type ConnectionIndexRequest = ConnectionTrustRequest;
|
|
72
|
+
/** Root/index response operations owned by the browser-token exchange. */
|
|
73
|
+
export interface ConnectionIndexResponse {
|
|
74
|
+
writeHead(status: number, headers?: Readonly<Record<string, string>>): unknown;
|
|
75
|
+
end(body?: string): unknown;
|
|
76
|
+
}
|
|
77
|
+
/** Outcome of admitting one request: the operator Peer it speaks for, or the status refusing it. */
|
|
78
|
+
export type PeerAdmission = {
|
|
79
|
+
readonly peer: PeerScope;
|
|
80
|
+
} | {
|
|
81
|
+
readonly rejection: 401 | 403;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Handler invoked after Connection has decoded the transport envelope.
|
|
85
|
+
* `peer` is the Peer the request was admitted as: the operator.
|
|
86
|
+
*/
|
|
87
|
+
export type ConnectionRpcHandler = (endpoint: string, payload: unknown, signal: AbortSignal, peer: PeerScope) => Promise<ConnectionRpcResult<unknown>>;
|
|
88
|
+
/** Synchronous ownership test for one endpoint on a shared RPC channel. */
|
|
89
|
+
export type ConnectionRpcEndpointMatcher = (endpoint: string) => boolean;
|
|
90
|
+
/** HTTP methods supported by exact Fetch routes on the shared API channel. */
|
|
91
|
+
export type ConnectionFetchMethod = 'GET' | 'HEAD' | 'POST';
|
|
92
|
+
/** How the node:http bridge presents one request body to its Fetch route. */
|
|
93
|
+
export type ConnectionRequestBodyMode = 'buffered' | 'streaming';
|
|
94
|
+
/** One exact, transport-independent Fetch route owned by a Host feature. */
|
|
95
|
+
export interface ConnectionFetchRoute {
|
|
96
|
+
/** Absolute path below `/api`; query parameters remain available on the request URL. */
|
|
97
|
+
readonly path: string;
|
|
98
|
+
/** Methods this route owns. Other methods continue through normal shared-channel dispatch. */
|
|
99
|
+
readonly methods: readonly ConnectionFetchMethod[];
|
|
100
|
+
/** Buffered requests obey the configured JSON cap; streaming requests arrive with backpressure and no aggregate cap. */
|
|
101
|
+
readonly requestBody: ConnectionRequestBodyMode;
|
|
102
|
+
/** Handle one request after the physical carrier has applied its trust and authentication policy. */
|
|
103
|
+
readonly fetch: (request: Request) => Promise<Response>;
|
|
104
|
+
}
|
|
105
|
+
/** Host registry for exact Fetch routes that cannot use JSON Remote invocation. */
|
|
106
|
+
export interface HostConnectionFetch {
|
|
107
|
+
/**
|
|
108
|
+
* Register one exact route on the shared API channel.
|
|
109
|
+
* @param route - path, methods, and Fetch-shaped implementation.
|
|
110
|
+
* @returns asynchronous disposer removing this exact contribution.
|
|
111
|
+
*/
|
|
112
|
+
register(route: ConnectionFetchRoute): () => Promise<void>;
|
|
113
|
+
}
|
|
114
|
+
/** Host registry for logical RPC channels carried by the current transport. */
|
|
115
|
+
export interface HostConnectionRpc {
|
|
116
|
+
/**
|
|
117
|
+
* Register one authenticated absolute channel prefix.
|
|
118
|
+
* @param channel - absolute logical channel such as `/rpc`.
|
|
119
|
+
* @param handler - decoded endpoint handler returning the existing RPC result shape.
|
|
120
|
+
* @returns asynchronous disposer removing the channel and its physical route.
|
|
121
|
+
*/
|
|
122
|
+
handle(channel: string, handler: ConnectionRpcHandler): () => Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Intercept owned endpoints on the shared `/api` channel before its fallback.
|
|
125
|
+
* @param channel - reserved shared channel; currently `/api`.
|
|
126
|
+
* @param matches - synchronous endpoint ownership test.
|
|
127
|
+
* @param handler - decoded endpoint handler returning the existing RPC result shape.
|
|
128
|
+
* @returns asynchronous disposer removing the interceptor.
|
|
129
|
+
*/
|
|
130
|
+
intercept(channel: '/api', matches: ConnectionRpcEndpointMatcher, handler: ConnectionRpcHandler): () => Promise<void>;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* One account session's verdicts for the transport gates. The authentication
|
|
134
|
+
* plugin owns them; Connection owns the enforcement points (every configured
|
|
135
|
+
* index path and the shared `/api` route) and never inspects session state
|
|
136
|
+
* itself.
|
|
137
|
+
*/
|
|
138
|
+
export interface ConnectionSessionAuthority {
|
|
139
|
+
/**
|
|
140
|
+
* Own the browser response for one gated index request.
|
|
141
|
+
* @param request - entry or configured-index HTTP request.
|
|
142
|
+
* @param response - response owned when this returns false.
|
|
143
|
+
* @returns true when the caller may serve the index document.
|
|
144
|
+
*/
|
|
145
|
+
authorizeIndex(request: ConnectionIndexRequest, response: ConnectionIndexResponse): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Whether one `/api` request needs no session because it belongs to the
|
|
148
|
+
* authentication surface itself.
|
|
149
|
+
* @param request - incoming request headers and target.
|
|
150
|
+
* @returns true when the request may proceed without an account session.
|
|
151
|
+
*/
|
|
152
|
+
isPublicApiRequest(request: ConnectionTrustRequest): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Verify the request's account session.
|
|
155
|
+
* @param request - incoming request headers.
|
|
156
|
+
* @returns true only for an unexpired session this authority issued.
|
|
157
|
+
*/
|
|
158
|
+
verify(request: ConnectionTrustRequest): boolean;
|
|
159
|
+
}
|
|
160
|
+
/** Registration seat for the one account-session authority of this transport. */
|
|
161
|
+
export interface HostConnectionSession {
|
|
162
|
+
/**
|
|
163
|
+
* Install the account-session authority consulted by the index and `/api`
|
|
164
|
+
* gates. One owner: a second installation fails the installing plugin's
|
|
165
|
+
* load, because two session authorities cannot compose. The seat belongs to
|
|
166
|
+
* the installing plugin's fiber, so disposing it releases the seat.
|
|
167
|
+
* @param authority - the authentication capability's verdicts.
|
|
168
|
+
*/
|
|
169
|
+
install(authority: ConnectionSessionAuthority): void;
|
|
170
|
+
}
|
|
171
|
+
/** Host `ctx.connection` members consumed by transport-independent adapters. */
|
|
172
|
+
export interface HostConnectionHandle {
|
|
173
|
+
/** Generic RPC channel registry. */
|
|
174
|
+
readonly rpc: HostConnectionRpc;
|
|
175
|
+
/** Exact Fetch routes for streaming or browser-native responses. */
|
|
176
|
+
readonly fetch: HostConnectionFetch;
|
|
177
|
+
/** The operator Peer every admitted request speaks for; its scope lives as long as Connection. */
|
|
178
|
+
readonly operator: PeerScope;
|
|
179
|
+
/** Account-session gate seat; unclaimed keeps device-token authentication. */
|
|
180
|
+
readonly session: HostConnectionSession;
|
|
181
|
+
/**
|
|
182
|
+
* Request path serving the application document: the launch-token handoff
|
|
183
|
+
* target, and therefore the index path every dist server must mount.
|
|
184
|
+
*/
|
|
185
|
+
readonly entryPath: string;
|
|
186
|
+
/**
|
|
187
|
+
* Compose exact Fetch routes and the shared-channel RPC interceptor.
|
|
188
|
+
* @param channel - shared channel mounted by Connection.
|
|
189
|
+
* @returns Fetch handler for trusted, authenticated requests.
|
|
190
|
+
*/
|
|
191
|
+
createSharedFetchHandler(channel: '/api'): ConnectionFetchHandler;
|
|
192
|
+
/**
|
|
193
|
+
* Apply Connection's Host/Origin checks and browser authentication to
|
|
194
|
+
* another Web route.
|
|
195
|
+
* @param request - request headers from the HTTP or upgrade request.
|
|
196
|
+
* @returns rejection status, or undefined when the route may accept the request.
|
|
197
|
+
*/
|
|
198
|
+
requestRejection(request: ConnectionTrustRequest): ConnectionRequestRejection;
|
|
199
|
+
/**
|
|
200
|
+
* Admit one request: it passes {@link requestRejection} and speaks for the
|
|
201
|
+
* operator, or it is refused with that status.
|
|
202
|
+
* @param request - request headers from the HTTP or upgrade request.
|
|
203
|
+
* @returns the operator Peer, or the rejection status.
|
|
204
|
+
*/
|
|
205
|
+
admit(request: ConnectionTrustRequest): PeerAdmission;
|
|
206
|
+
/**
|
|
207
|
+
* Authenticate one frontend index request, owning a token redirect or 401.
|
|
208
|
+
* @param request - root or configured-index HTTP request.
|
|
209
|
+
* @param response - response owned when the result is false.
|
|
210
|
+
* @returns true only when the frontend may serve index.html.
|
|
211
|
+
*/
|
|
212
|
+
authorizeIndex(request: ConnectionIndexRequest, response: ConnectionIndexResponse): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Add the fresh process token to an ordinary Web application URL.
|
|
215
|
+
* @param baseUrl - clean canonical browser origin.
|
|
216
|
+
* @param displayName - optional operator name carried into the device cookie for display.
|
|
217
|
+
* @returns root URL accepted by {@link authorizeIndex} for initial login.
|
|
218
|
+
*/
|
|
219
|
+
authenticatedUrl(baseUrl: string, displayName?: string): string;
|
|
220
|
+
}
|
|
221
|
+
/** Transport-independent Fetch handler used by HTTP and worker carriers. */
|
|
222
|
+
export interface ConnectionFetchHandler {
|
|
223
|
+
/**
|
|
224
|
+
* Resolve body handling before the bridge reads any request bytes.
|
|
225
|
+
* @param request - request method and URL available from node:http headers.
|
|
226
|
+
* @returns the registered route's body handling mode.
|
|
227
|
+
*/
|
|
228
|
+
requestBodyMode(request: {
|
|
229
|
+
readonly method: string;
|
|
230
|
+
readonly url: URL;
|
|
231
|
+
}): ConnectionRequestBodyMode;
|
|
232
|
+
/**
|
|
233
|
+
* Dispatch one already-authenticated request.
|
|
234
|
+
* @param request - Fetch request below the shared channel.
|
|
235
|
+
* @returns the registered response or a 404 response.
|
|
236
|
+
*/
|
|
237
|
+
fetch(request: Request): Promise<Response>;
|
|
238
|
+
}
|
|
239
|
+
/** Client caller for logical RPC channels carried by the current transport. */
|
|
240
|
+
export interface ClientConnectionRpc {
|
|
241
|
+
/**
|
|
242
|
+
* Call one endpoint through an already registered logical channel.
|
|
243
|
+
* @param channel - absolute logical channel such as `/api`.
|
|
244
|
+
* @param endpoint - channel-relative endpoint such as `goals/create`.
|
|
245
|
+
* @param payload - channel-owned request payload.
|
|
246
|
+
* @param signal - optional caller cancellation.
|
|
247
|
+
* @returns the endpoint-owned success/error result; correlation stays inside Connection.
|
|
248
|
+
*/
|
|
249
|
+
call(channel: string, endpoint: string, payload: unknown, signal?: AbortSignal): Promise<ConnectionRpcResult<unknown>>;
|
|
250
|
+
/**
|
|
251
|
+
* Open an in-process logical stream when the selected carrier supplies one.
|
|
252
|
+
* Browser transports omit this method; API Gateway owns their WebSocket mux.
|
|
253
|
+
* @param channel - absolute logical channel such as `/api`.
|
|
254
|
+
* @param endpoint - channel-relative endpoint such as `session/follow`.
|
|
255
|
+
* @param payload - channel-owned request payload.
|
|
256
|
+
* @param signal - caller cancellation for this logical stream.
|
|
257
|
+
* @param uplink - Client uplink items the Host method reads through `invocation.uplink()`.
|
|
258
|
+
* @returns decoded stream values from the in-process carrier.
|
|
259
|
+
*/
|
|
260
|
+
readonly open?: (channel: string, endpoint: string, payload: unknown, signal: AbortSignal, uplink?: AsyncIterable<unknown>) => AsyncIterable<unknown>;
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=rpc.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one request path that serves the harness application document. The site
|
|
3
|
+
* root keeps the public landing page and the sign-in screens have their own
|
|
4
|
+
* documents, so every entry URL, redirect, and deployment index path names
|
|
5
|
+
* this constant instead of repeating the literal.
|
|
6
|
+
*/
|
|
7
|
+
/** Request path serving the harness application document. */
|
|
8
|
+
export declare const WEB_ENTRY_PATH = "/workspace";
|
|
9
|
+
//# sourceMappingURL=web-entry.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qilin-agent/client-connection",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"description": "Authenticated RPC transport and generation lifecycle",
|
|
4
|
+
"version": "3.1.3",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/kkutysllb/QiLin.git",
|
|
11
|
+
"directory": "packages/client/connection"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"types": "lib/types/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./lib/types/index.d.ts",
|
|
22
|
+
"default": "./lib/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./client": {
|
|
25
|
+
"types": "./lib/types/client/index.d.ts",
|
|
26
|
+
"default": "./lib/client.js"
|
|
27
|
+
},
|
|
28
|
+
"./src/*": "./src/*",
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"qilin": {
|
|
32
|
+
"client": {
|
|
33
|
+
"inject": [],
|
|
34
|
+
"platform": "web",
|
|
35
|
+
"immediately": true
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"zod": "^4.4.3",
|
|
41
|
+
"@qilin-agent/credentials": "3.1.3",
|
|
42
|
+
"@qilin-agent/schemastery": "~3.18.3"
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"lib/index.js",
|
|
46
|
+
"lib/client.js",
|
|
47
|
+
"lib/types/**/*.d.ts"
|
|
48
|
+
],
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@qilin-agent/scope": "3.1.3",
|
|
51
|
+
"@qilin-agent/kylin": "~4.0.3"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@qilin-agent/kylin": "~4.0.3",
|
|
55
|
+
"@qilin-agent/attachment": "3.1.3",
|
|
56
|
+
"@qilin-agent/brand": "3.1.3",
|
|
57
|
+
"@qilin-agent/host-webserver": "3.1.3",
|
|
58
|
+
"@qilin-agent/llm": "3.1.3",
|
|
59
|
+
"@qilin-agent/scope": "3.1.3",
|
|
60
|
+
"@qilin-agent/session": "3.1.3",
|
|
61
|
+
"@qilin-agent/typert-protocol": "3.1.3",
|
|
62
|
+
"@qilin-agent/tool-todo": "3.1.3",
|
|
63
|
+
"@qilin-agent/util-values": "3.1.3",
|
|
64
|
+
"@qilin-agent/commands": "3.1.3",
|
|
65
|
+
"@qilin-agent/settings": "3.1.3",
|
|
66
|
+
"@qilin-agent/host-directory-picker": "3.1.3"
|
|
67
|
+
}
|
|
6
68
|
}
|