@iicp/client 0.5.7 → 0.7.0
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/availability.d.ts +30 -0
- package/dist/availability.d.ts.map +1 -0
- package/dist/availability.js +64 -0
- package/dist/availability.js.map +1 -0
- package/dist/backends/base.d.ts +35 -0
- package/dist/backends/base.d.ts.map +1 -0
- package/dist/backends/base.js +97 -0
- package/dist/backends/base.js.map +1 -0
- package/dist/backends/index.d.ts +13 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +30 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/llamacpp.d.ts +18 -0
- package/dist/backends/llamacpp.d.ts.map +1 -0
- package/dist/backends/llamacpp.js +17 -0
- package/dist/backends/llamacpp.js.map +1 -0
- package/dist/backends/openai_compat.d.ts +6 -10
- package/dist/backends/openai_compat.d.ts.map +1 -1
- package/dist/backends/openai_compat.js +5 -78
- package/dist/backends/openai_compat.js.map +1 -1
- package/dist/backends/vllm.d.ts +19 -0
- package/dist/backends/vllm.d.ts.map +1 -0
- package/dist/backends/vllm.js +17 -0
- package/dist/backends/vllm.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +34 -2
- package/dist/cli.js.map +1 -1
- package/dist/idempotency.d.ts +17 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +39 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/iicp_tcp.d.ts +4 -1
- package/dist/iicp_tcp.d.ts.map +1 -1
- package/dist/iicp_tcp.js +3 -0
- package/dist/iicp_tcp.js.map +1 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/nat_detection.d.ts +4 -0
- package/dist/nat_detection.d.ts.map +1 -1
- package/dist/nat_detection.js +19 -0
- package/dist/nat_detection.js.map +1 -1
- package/dist/node.d.ts +45 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +349 -59
- package/dist/node.js.map +1 -1
- package/dist/otel_tracer.d.ts +26 -0
- package/dist/otel_tracer.d.ts.map +1 -0
- package/dist/otel_tracer.js +96 -0
- package/dist/otel_tracer.js.map +1 -0
- package/dist/peer_manager.d.ts +54 -0
- package/dist/peer_manager.d.ts.map +1 -0
- package/dist/peer_manager.js +184 -0
- package/dist/peer_manager.js.map +1 -0
- package/dist/relay_session.d.ts +42 -0
- package/dist/relay_session.d.ts.map +1 -0
- package/dist/relay_session.js +276 -0
- package/dist/relay_session.js.map +1 -0
- package/dist/relay_worker_client.d.ts +37 -0
- package/dist/relay_worker_client.d.ts.map +1 -0
- package/dist/relay_worker_client.js +216 -0
- package/dist/relay_worker_client.js.map +1 -0
- package/dist/scheduler.d.ts +23 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +42 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/token_validator.d.ts +15 -0
- package/dist/token_validator.d.ts.map +1 -0
- package/dist/token_validator.js +34 -0
- package/dist/token_validator.js.map +1 -0
- package/dist/trust_auditor.d.ts +34 -0
- package/dist/trust_auditor.d.ts.map +1 -0
- package/dist/trust_auditor.js +123 -0
- package/dist/trust_auditor.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Relay-as-last-resort — ADR-041 tier-3, Part 3 R1 (#341).
|
|
5
|
+
*
|
|
6
|
+
* TypeScript port of iicp-client-python/relay_session.py.
|
|
7
|
+
* Workers behind CGNAT hold an outbound IICP-TCP connection here.
|
|
8
|
+
* The relay pushes CALL frames down when /v1/relay is invoked and routes
|
|
9
|
+
* RESPONSE frames back to the waiting HTTP handler.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RelayAcceptServer = exports.RelaySessionRegistry = exports.RelayWorkerSession = void 0;
|
|
13
|
+
const net = require("node:net");
|
|
14
|
+
const IICP_MAGIC = Buffer.from("IICP");
|
|
15
|
+
const FRAMING_VERSION = 0x01;
|
|
16
|
+
const FRAME_HEADER_LEN = 12;
|
|
17
|
+
// Frame type constants (mirrors MsgType enum in iicp_tcp.ts)
|
|
18
|
+
const MT_INIT = 0x01;
|
|
19
|
+
const MT_ACK = 0x02;
|
|
20
|
+
const MT_CALL = 0x05;
|
|
21
|
+
const MT_RESPONSE = 0x06;
|
|
22
|
+
const MT_CLOSE = 0x07;
|
|
23
|
+
const MT_PING = 0x09;
|
|
24
|
+
const MT_PONG = 0x0a;
|
|
25
|
+
const MT_RELAY_BIND = 0x0b;
|
|
26
|
+
const MT_RELAY_ACK = 0x0c;
|
|
27
|
+
function _enc(obj) {
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
29
|
+
const cbor = require("cbor-x");
|
|
30
|
+
return cbor.encode(obj);
|
|
31
|
+
}
|
|
32
|
+
function _dec(buf) {
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
34
|
+
const cbor = require("cbor-x");
|
|
35
|
+
return cbor.decode(buf);
|
|
36
|
+
}
|
|
37
|
+
function makeFrame(msgType, payload) {
|
|
38
|
+
const header = Buffer.alloc(FRAME_HEADER_LEN);
|
|
39
|
+
IICP_MAGIC.copy(header, 0);
|
|
40
|
+
header.writeUInt8(FRAMING_VERSION, 4);
|
|
41
|
+
header.writeUInt8(msgType, 5);
|
|
42
|
+
header.writeUInt8(0, 6); // flags
|
|
43
|
+
header.writeUInt8(0, 7); // reserved
|
|
44
|
+
header.writeUInt32BE(payload.length, 8);
|
|
45
|
+
return Buffer.concat([header, payload]);
|
|
46
|
+
}
|
|
47
|
+
// ── RelayWorkerSession ────────────────────────────────────────────────────────
|
|
48
|
+
class RelayWorkerSession {
|
|
49
|
+
workerId;
|
|
50
|
+
_socket;
|
|
51
|
+
_pending = new Map();
|
|
52
|
+
_writeLocked = false;
|
|
53
|
+
constructor(workerId, socket) {
|
|
54
|
+
this.workerId = workerId;
|
|
55
|
+
this._socket = socket;
|
|
56
|
+
}
|
|
57
|
+
/** Push a task CALL to the worker and await the RESPONSE (via Promise). */
|
|
58
|
+
async forwardTask(task, timeoutMs = 120_000) {
|
|
59
|
+
const callId = crypto.randomUUID();
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const timer = setTimeout(() => {
|
|
62
|
+
this._pending.delete(callId);
|
|
63
|
+
reject(new Error(`relay forward timeout for call ${callId}`));
|
|
64
|
+
}, timeoutMs);
|
|
65
|
+
this._pending.set(callId, (result) => {
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
resolve(result);
|
|
68
|
+
});
|
|
69
|
+
try {
|
|
70
|
+
const payload = _enc({ 15: callId, 5: Buffer.from(JSON.stringify(task)) });
|
|
71
|
+
const frame = makeFrame(MT_CALL, payload);
|
|
72
|
+
this._socket.write(frame);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
this._pending.delete(callId);
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
reject(err);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/** Called by relay accept server when a RESPONSE arrives from the worker. */
|
|
82
|
+
onResponse(callId, result) {
|
|
83
|
+
const cb = this._pending.get(callId);
|
|
84
|
+
if (cb) {
|
|
85
|
+
this._pending.delete(callId);
|
|
86
|
+
cb(result);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.RelayWorkerSession = RelayWorkerSession;
|
|
91
|
+
// ── RelaySessionRegistry ─────────────────────────────────────────────────────
|
|
92
|
+
class RelaySessionRegistry {
|
|
93
|
+
_sessions = new Map();
|
|
94
|
+
bind(workerId, session) {
|
|
95
|
+
this._sessions.set(workerId, session);
|
|
96
|
+
}
|
|
97
|
+
unbind(workerId) {
|
|
98
|
+
this._sessions.delete(workerId);
|
|
99
|
+
}
|
|
100
|
+
get(workerId) {
|
|
101
|
+
return this._sessions.get(workerId);
|
|
102
|
+
}
|
|
103
|
+
isBound(workerId) {
|
|
104
|
+
return this._sessions.has(workerId);
|
|
105
|
+
}
|
|
106
|
+
boundWorkerIds() {
|
|
107
|
+
return [...this._sessions.keys()];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.RelaySessionRegistry = RelaySessionRegistry;
|
|
111
|
+
// ── RelayAcceptServer ─────────────────────────────────────────────────────────
|
|
112
|
+
class RelayAcceptServer {
|
|
113
|
+
_registry;
|
|
114
|
+
_host;
|
|
115
|
+
_port;
|
|
116
|
+
_server;
|
|
117
|
+
constructor(registry, opts = {}) {
|
|
118
|
+
this._registry = registry;
|
|
119
|
+
this._host = opts.host ?? "0.0.0.0";
|
|
120
|
+
this._port = opts.port ?? 9485;
|
|
121
|
+
}
|
|
122
|
+
start() {
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
this._server = net.createServer((socket) => {
|
|
125
|
+
this._handleConnection(socket).catch((err) => {
|
|
126
|
+
console.error(`[relay-accept] session error: ${err instanceof Error ? err.message : err}`);
|
|
127
|
+
socket.destroy();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
this._server.listen(this._port, this._host, () => {
|
|
131
|
+
console.log(`[relay-accept] listening on ${this._host}:${this._port}`);
|
|
132
|
+
resolve();
|
|
133
|
+
});
|
|
134
|
+
this._server.on("error", reject);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
stop() {
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
if (this._server) {
|
|
140
|
+
this._server.close(() => resolve());
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
resolve();
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
async _handleConnection(socket) {
|
|
148
|
+
// Accumulate data into a buffer for synchronous frame parsing
|
|
149
|
+
const chunks = [];
|
|
150
|
+
let resolveData = null;
|
|
151
|
+
socket.on("data", (d) => {
|
|
152
|
+
chunks.push(d);
|
|
153
|
+
if (resolveData) {
|
|
154
|
+
resolveData();
|
|
155
|
+
resolveData = null;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
socket.on("end", () => { if (resolveData) {
|
|
159
|
+
resolveData();
|
|
160
|
+
resolveData = null;
|
|
161
|
+
} });
|
|
162
|
+
socket.on("error", () => { if (resolveData) {
|
|
163
|
+
resolveData();
|
|
164
|
+
resolveData = null;
|
|
165
|
+
} });
|
|
166
|
+
const waitForData = () => new Promise((r) => { resolveData = r; });
|
|
167
|
+
const readExactly = async (n) => {
|
|
168
|
+
while (true) {
|
|
169
|
+
let total = chunks.reduce((s, c) => s + c.length, 0);
|
|
170
|
+
if (total >= n) {
|
|
171
|
+
const merged = Buffer.concat(chunks);
|
|
172
|
+
chunks.length = 0;
|
|
173
|
+
chunks.push(merged.subarray(n));
|
|
174
|
+
return merged.subarray(0, n);
|
|
175
|
+
}
|
|
176
|
+
if (socket.destroyed)
|
|
177
|
+
return null;
|
|
178
|
+
await waitForData();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
// Step 1: INIT
|
|
182
|
+
const magic = await readExactly(4);
|
|
183
|
+
if (!magic || !magic.equals(IICP_MAGIC))
|
|
184
|
+
return;
|
|
185
|
+
const rest = await readExactly(FRAME_HEADER_LEN - 4);
|
|
186
|
+
if (!rest)
|
|
187
|
+
return;
|
|
188
|
+
const header = Buffer.concat([magic, rest]);
|
|
189
|
+
const msgType = header.readUInt8(5);
|
|
190
|
+
const payloadLen = header.readUInt32BE(8);
|
|
191
|
+
if (msgType !== MT_INIT)
|
|
192
|
+
return;
|
|
193
|
+
if (payloadLen > 0) {
|
|
194
|
+
const _ = await readExactly(payloadLen);
|
|
195
|
+
if (!_)
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
socket.write(makeFrame(MT_ACK, _enc({ 1: FRAMING_VERSION })));
|
|
199
|
+
// Step 2: RELAY_BIND
|
|
200
|
+
const rh = await readExactly(FRAME_HEADER_LEN);
|
|
201
|
+
if (!rh)
|
|
202
|
+
return;
|
|
203
|
+
const rmt = rh.readUInt8(5);
|
|
204
|
+
const rlen = rh.readUInt32BE(8);
|
|
205
|
+
if (rmt !== MT_RELAY_BIND)
|
|
206
|
+
return;
|
|
207
|
+
const rbuf = rlen > 0 ? await readExactly(rlen) : Buffer.alloc(0);
|
|
208
|
+
if (!rbuf)
|
|
209
|
+
return;
|
|
210
|
+
let workerId, intent, models;
|
|
211
|
+
try {
|
|
212
|
+
const body = _dec(rbuf);
|
|
213
|
+
workerId = String(body[1] ?? "");
|
|
214
|
+
intent = String(body[2] ?? "");
|
|
215
|
+
models = Array.isArray(body[3]) ? body[3].map(String) : [];
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (!workerId)
|
|
221
|
+
return;
|
|
222
|
+
const session = new RelayWorkerSession(workerId, socket);
|
|
223
|
+
this._registry.bind(workerId, session);
|
|
224
|
+
console.log(`[relay-accept] worker=${workerId} bound (intent=${intent} models=${models.slice(0, 3).join(",")})`);
|
|
225
|
+
socket.write(makeFrame(MT_RELAY_ACK, _enc({ 1: "ok", 2: workerId })));
|
|
226
|
+
// Step 3: relay-worker frame loop
|
|
227
|
+
try {
|
|
228
|
+
while (!socket.destroyed) {
|
|
229
|
+
const fh = await readExactly(FRAME_HEADER_LEN);
|
|
230
|
+
if (!fh)
|
|
231
|
+
break;
|
|
232
|
+
const ft = fh.readUInt8(5);
|
|
233
|
+
const fl = fh.readUInt32BE(8);
|
|
234
|
+
const fp = fl > 0 ? await readExactly(fl) : Buffer.alloc(0);
|
|
235
|
+
if (!fp)
|
|
236
|
+
break;
|
|
237
|
+
if (ft === MT_PING) {
|
|
238
|
+
let echo = Buffer.alloc(0);
|
|
239
|
+
try {
|
|
240
|
+
const pb = _dec(fp);
|
|
241
|
+
const e = pb[1];
|
|
242
|
+
echo = Buffer.isBuffer(e) ? Buffer.from(e) : Buffer.alloc(0);
|
|
243
|
+
}
|
|
244
|
+
catch { /* ok */ }
|
|
245
|
+
socket.write(makeFrame(MT_PONG, _enc({ 1: echo })));
|
|
246
|
+
}
|
|
247
|
+
else if (ft === MT_RESPONSE) {
|
|
248
|
+
try {
|
|
249
|
+
const rb = _dec(fp);
|
|
250
|
+
const callId = String(rb[15] ?? "");
|
|
251
|
+
const raw5 = rb[5];
|
|
252
|
+
let result = {};
|
|
253
|
+
if (Buffer.isBuffer(raw5))
|
|
254
|
+
result = JSON.parse(raw5.toString());
|
|
255
|
+
else if (typeof raw5 === "string")
|
|
256
|
+
result = JSON.parse(raw5);
|
|
257
|
+
session.onResponse(callId, result);
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
console.warn(`[relay-accept] RESPONSE decode error: ${err}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else if (ft === MT_CLOSE) {
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
this._registry.unbind(workerId);
|
|
270
|
+
console.log(`[relay-accept] session ended for worker=${workerId}`);
|
|
271
|
+
socket.destroy();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
exports.RelayAcceptServer = RelayAcceptServer;
|
|
276
|
+
//# sourceMappingURL=relay_session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay_session.js","sourceRoot":"","sources":["../src/relay_session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relay worker client — ADR-041 tier-3, Part 3 R2 (#341).
|
|
3
|
+
*
|
|
4
|
+
* TypeScript port of relay_worker_client.py.
|
|
5
|
+
* A CGNAT-unreachable node connects outbound to a relay node here.
|
|
6
|
+
* The relay pushes CALL frames down the persistent session; the worker
|
|
7
|
+
* handles them and sends RESPONSE back. PING/PONG keepalive with auto-
|
|
8
|
+
* reconnect (exponential backoff, cap 60 s).
|
|
9
|
+
*/
|
|
10
|
+
export type RelayTaskHandler = (task: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
11
|
+
export declare class RelayWorkerClient {
|
|
12
|
+
private readonly _workerId;
|
|
13
|
+
private readonly _intent;
|
|
14
|
+
private readonly _relayHost;
|
|
15
|
+
private readonly _relayPort;
|
|
16
|
+
private readonly _handler;
|
|
17
|
+
private readonly _models;
|
|
18
|
+
private readonly _onBind?;
|
|
19
|
+
private _stopped;
|
|
20
|
+
constructor(opts: {
|
|
21
|
+
workerId: string;
|
|
22
|
+
intent: string;
|
|
23
|
+
relayHost: string;
|
|
24
|
+
relayPort: number;
|
|
25
|
+
handler: RelayTaskHandler;
|
|
26
|
+
models?: string[];
|
|
27
|
+
/** Called after a successful RELAY_ACK — use to re-register with the directory (#358). */
|
|
28
|
+
onBind?: (relayHost: string, relayPort: number, workerId: string) => Promise<void>;
|
|
29
|
+
});
|
|
30
|
+
/** Start the reconnect loop. Returns a stop() function. */
|
|
31
|
+
start(): () => void;
|
|
32
|
+
private _run;
|
|
33
|
+
private _session;
|
|
34
|
+
private _handshake;
|
|
35
|
+
private _handleCall;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=relay_worker_client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay_worker_client.d.ts","sourceRoot":"","sources":["../src/relay_worker_client.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAwCH,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEnG,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAA4E;IACrG,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,gBAAgB,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,0FAA0F;QAC1F,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACpF;IAUD,2DAA2D;IAC3D,KAAK,IAAI,MAAM,IAAI;YAML,IAAI;IAelB,OAAO,CAAC,QAAQ;YAaF,UAAU;YAoFV,WAAW;CAoB1B"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Relay worker client — ADR-041 tier-3, Part 3 R2 (#341).
|
|
5
|
+
*
|
|
6
|
+
* TypeScript port of relay_worker_client.py.
|
|
7
|
+
* A CGNAT-unreachable node connects outbound to a relay node here.
|
|
8
|
+
* The relay pushes CALL frames down the persistent session; the worker
|
|
9
|
+
* handles them and sends RESPONSE back. PING/PONG keepalive with auto-
|
|
10
|
+
* reconnect (exponential backoff, cap 60 s).
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.RelayWorkerClient = void 0;
|
|
14
|
+
const net = require("node:net");
|
|
15
|
+
const IICP_MAGIC = Buffer.from("IICP");
|
|
16
|
+
const FRAMING_VERSION = 0x01;
|
|
17
|
+
const FRAME_HEADER_LEN = 12;
|
|
18
|
+
const PING_INTERVAL_MS = 30_000;
|
|
19
|
+
const MAX_RECONNECT_DELAY_MS = 60_000;
|
|
20
|
+
const MT_INIT = 0x01;
|
|
21
|
+
const MT_ACK = 0x02;
|
|
22
|
+
const MT_CALL = 0x05;
|
|
23
|
+
const MT_RESPONSE = 0x06;
|
|
24
|
+
const MT_PING = 0x09;
|
|
25
|
+
const MT_PONG = 0x0a;
|
|
26
|
+
const MT_RELAY_BIND = 0x0b;
|
|
27
|
+
const MT_RELAY_ACK = 0x0c;
|
|
28
|
+
function _enc(obj) {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
30
|
+
return require("cbor-x").encode(obj);
|
|
31
|
+
}
|
|
32
|
+
function _dec(buf) {
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
34
|
+
return require("cbor-x").decode(buf);
|
|
35
|
+
}
|
|
36
|
+
function makeFrame(msgType, payload) {
|
|
37
|
+
const header = Buffer.alloc(FRAME_HEADER_LEN);
|
|
38
|
+
IICP_MAGIC.copy(header, 0);
|
|
39
|
+
header.writeUInt8(FRAMING_VERSION, 4);
|
|
40
|
+
header.writeUInt8(msgType, 5);
|
|
41
|
+
header.writeUInt8(0, 6);
|
|
42
|
+
header.writeUInt8(0, 7);
|
|
43
|
+
header.writeUInt32BE(payload.length, 8);
|
|
44
|
+
return Buffer.concat([header, payload]);
|
|
45
|
+
}
|
|
46
|
+
class RelayWorkerClient {
|
|
47
|
+
_workerId;
|
|
48
|
+
_intent;
|
|
49
|
+
_relayHost;
|
|
50
|
+
_relayPort;
|
|
51
|
+
_handler;
|
|
52
|
+
_models;
|
|
53
|
+
_onBind;
|
|
54
|
+
_stopped = false;
|
|
55
|
+
constructor(opts) {
|
|
56
|
+
this._workerId = opts.workerId;
|
|
57
|
+
this._intent = opts.intent;
|
|
58
|
+
this._relayHost = opts.relayHost;
|
|
59
|
+
this._relayPort = opts.relayPort;
|
|
60
|
+
this._handler = opts.handler;
|
|
61
|
+
this._models = opts.models ?? [];
|
|
62
|
+
this._onBind = opts.onBind;
|
|
63
|
+
}
|
|
64
|
+
/** Start the reconnect loop. Returns a stop() function. */
|
|
65
|
+
start() {
|
|
66
|
+
this._stopped = false;
|
|
67
|
+
void this._run();
|
|
68
|
+
return () => { this._stopped = true; };
|
|
69
|
+
}
|
|
70
|
+
async _run() {
|
|
71
|
+
let delay = 2_000;
|
|
72
|
+
while (!this._stopped) {
|
|
73
|
+
try {
|
|
74
|
+
await this._session();
|
|
75
|
+
delay = 2_000;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// reconnect
|
|
79
|
+
}
|
|
80
|
+
if (this._stopped)
|
|
81
|
+
break;
|
|
82
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
83
|
+
delay = Math.min(delay * 2, MAX_RECONNECT_DELAY_MS);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
_session() {
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
const socket = net.createConnection(this._relayPort, this._relayHost);
|
|
89
|
+
socket.on("error", reject);
|
|
90
|
+
socket.on("connect", () => {
|
|
91
|
+
this._handshake(socket)
|
|
92
|
+
.then(resolve)
|
|
93
|
+
.catch(reject)
|
|
94
|
+
.finally(() => socket.destroy());
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async _handshake(socket) {
|
|
99
|
+
const chunks = [];
|
|
100
|
+
let resolveData = null;
|
|
101
|
+
socket.on("data", (d) => {
|
|
102
|
+
chunks.push(d);
|
|
103
|
+
if (resolveData) {
|
|
104
|
+
resolveData();
|
|
105
|
+
resolveData = null;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
socket.on("end", () => { if (resolveData) {
|
|
109
|
+
resolveData();
|
|
110
|
+
resolveData = null;
|
|
111
|
+
} });
|
|
112
|
+
const waitData = () => new Promise((r) => { resolveData = r; });
|
|
113
|
+
const readExact = async (n) => {
|
|
114
|
+
while (true) {
|
|
115
|
+
const total = chunks.reduce((s, c) => s + c.length, 0);
|
|
116
|
+
if (total >= n) {
|
|
117
|
+
const merged = Buffer.concat(chunks);
|
|
118
|
+
chunks.length = 0;
|
|
119
|
+
chunks.push(merged.subarray(n));
|
|
120
|
+
return merged.subarray(0, n);
|
|
121
|
+
}
|
|
122
|
+
if (socket.destroyed)
|
|
123
|
+
return null;
|
|
124
|
+
await waitData();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const readFrame = async () => {
|
|
128
|
+
const h = await readExact(FRAME_HEADER_LEN);
|
|
129
|
+
if (!h)
|
|
130
|
+
return null;
|
|
131
|
+
if (!h.subarray(0, 4).equals(IICP_MAGIC))
|
|
132
|
+
return null;
|
|
133
|
+
const mt = h.readUInt8(5);
|
|
134
|
+
const plen = h.readUInt32BE(8);
|
|
135
|
+
const payload = plen > 0 ? await readExact(plen) : Buffer.alloc(0);
|
|
136
|
+
if (!payload)
|
|
137
|
+
return null;
|
|
138
|
+
return [mt, payload];
|
|
139
|
+
};
|
|
140
|
+
// Step 1: INIT → ACK
|
|
141
|
+
socket.write(makeFrame(MT_INIT, _enc({ 1: FRAMING_VERSION })));
|
|
142
|
+
const ack = await readFrame();
|
|
143
|
+
if (!ack || ack[0] !== MT_ACK)
|
|
144
|
+
throw new Error(`Expected ACK, got ${ack?.[0]}`);
|
|
145
|
+
// Step 2: RELAY_BIND → RELAY_ACK
|
|
146
|
+
socket.write(makeFrame(MT_RELAY_BIND, _enc({
|
|
147
|
+
1: this._workerId,
|
|
148
|
+
2: this._intent,
|
|
149
|
+
3: this._models,
|
|
150
|
+
})));
|
|
151
|
+
const rack = await readFrame();
|
|
152
|
+
if (!rack || rack[0] !== MT_RELAY_ACK)
|
|
153
|
+
throw new Error(`Expected RELAY_ACK, got ${rack?.[0]}`);
|
|
154
|
+
const ackBody = _dec(rack[1]);
|
|
155
|
+
if (ackBody[1] !== "ok")
|
|
156
|
+
throw new Error(`RELAY_ACK not ok: ${JSON.stringify(ackBody)}`);
|
|
157
|
+
console.log(`[relay-worker] ${this._workerId}: bound to relay ${this._relayHost}:${this._relayPort}`);
|
|
158
|
+
if (this._onBind) {
|
|
159
|
+
try {
|
|
160
|
+
await this._onBind(this._relayHost, this._relayPort, this._workerId);
|
|
161
|
+
}
|
|
162
|
+
catch (exc) {
|
|
163
|
+
console.warn(`[relay-worker] onBind callback failed: ${exc instanceof Error ? exc.message : exc}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Step 3: session loop
|
|
167
|
+
const pingTimer = setInterval(() => {
|
|
168
|
+
if (!socket.destroyed)
|
|
169
|
+
socket.write(makeFrame(MT_PING, _enc({ 1: Buffer.alloc(0) })));
|
|
170
|
+
}, PING_INTERVAL_MS);
|
|
171
|
+
try {
|
|
172
|
+
while (!this._stopped && !socket.destroyed) {
|
|
173
|
+
const frame = await readFrame();
|
|
174
|
+
if (!frame)
|
|
175
|
+
break;
|
|
176
|
+
const [mt, payload] = frame;
|
|
177
|
+
if (mt === MT_CALL) {
|
|
178
|
+
void this._handleCall(payload, socket);
|
|
179
|
+
}
|
|
180
|
+
else if (mt === MT_PONG || mt === MT_PING) {
|
|
181
|
+
// keepalive acknowledged / or relay's keepalive
|
|
182
|
+
}
|
|
183
|
+
else if (mt === 0x07) {
|
|
184
|
+
break; // CLOSE
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
clearInterval(pingTimer);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async _handleCall(payload, socket) {
|
|
193
|
+
let callId = "";
|
|
194
|
+
let result;
|
|
195
|
+
try {
|
|
196
|
+
const body = _dec(payload);
|
|
197
|
+
callId = String(body[15] ?? "");
|
|
198
|
+
const raw5 = body[5];
|
|
199
|
+
const taskStr = Buffer.isBuffer(raw5) ? raw5.toString() : String(raw5 ?? "{}");
|
|
200
|
+
const task = JSON.parse(taskStr);
|
|
201
|
+
result = await this._handler(task);
|
|
202
|
+
}
|
|
203
|
+
catch (exc) {
|
|
204
|
+
result = { error: exc instanceof Error ? exc.message : String(exc) };
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
const respPayload = _enc({ 15: callId, 5: Buffer.from(JSON.stringify(result)) });
|
|
208
|
+
socket.write(makeFrame(MT_RESPONSE, respPayload));
|
|
209
|
+
}
|
|
210
|
+
catch (exc) {
|
|
211
|
+
console.warn(`[relay-worker] failed to send RESPONSE: ${exc}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
exports.RelayWorkerClient = RelayWorkerClient;
|
|
216
|
+
//# sourceMappingURL=relay_worker_client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay_worker_client.js","sourceRoot":"","sources":["../src/relay_worker_client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QoS-aware admission policy for the provider serve path (parity Block C, #340).
|
|
3
|
+
*
|
|
4
|
+
* Port of the QoS *contract* from iicp-adapter `scheduling/queue.py`. The adapter runs a
|
|
5
|
+
* full PriorityQueue dispatcher; the SDK serve gate is deliberately fail-fast (queuing
|
|
6
|
+
* would hide overload from the proxy). To close the cat-8 parity gap without contradicting
|
|
7
|
+
* that design, the SDK applies QoS-aware admission:
|
|
8
|
+
*
|
|
9
|
+
* - realtime / interactive → queue-eligible: wait briefly (QUEUE_WAIT_MS) for a slot.
|
|
10
|
+
* - batch / best-effort / unspecified → fail fast with IICP-E021.
|
|
11
|
+
*
|
|
12
|
+
* Priority ordering (lower = higher priority) is exposed for telemetry parity.
|
|
13
|
+
*/
|
|
14
|
+
export declare const QOS_PRIORITY: Record<string, number>;
|
|
15
|
+
/** Tiers that wait briefly for a slot rather than failing fast at capacity. */
|
|
16
|
+
export declare const QUEUE_ELIGIBLE: ReadonlySet<string>;
|
|
17
|
+
/** Bounded wait for queue-eligible tiers (ms). */
|
|
18
|
+
export declare const QUEUE_WAIT_MS = 2000;
|
|
19
|
+
/** Priority rank for a QoS class (lower = higher priority; unknown → 3). */
|
|
20
|
+
export declare function qosPriority(qos: string | null | undefined): number;
|
|
21
|
+
/** True if a task of this QoS class should wait briefly for a slot at capacity. */
|
|
22
|
+
export declare function isQueueEligible(qos: string | null | undefined): boolean;
|
|
23
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;GAYG;AAGH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM/C,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAAwC,CAAC;AAExF,kDAAkD;AAClD,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGlE;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEvE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* QoS-aware admission policy for the provider serve path (parity Block C, #340).
|
|
5
|
+
*
|
|
6
|
+
* Port of the QoS *contract* from iicp-adapter `scheduling/queue.py`. The adapter runs a
|
|
7
|
+
* full PriorityQueue dispatcher; the SDK serve gate is deliberately fail-fast (queuing
|
|
8
|
+
* would hide overload from the proxy). To close the cat-8 parity gap without contradicting
|
|
9
|
+
* that design, the SDK applies QoS-aware admission:
|
|
10
|
+
*
|
|
11
|
+
* - realtime / interactive → queue-eligible: wait briefly (QUEUE_WAIT_MS) for a slot.
|
|
12
|
+
* - batch / best-effort / unspecified → fail fast with IICP-E021.
|
|
13
|
+
*
|
|
14
|
+
* Priority ordering (lower = higher priority) is exposed for telemetry parity.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.QUEUE_WAIT_MS = exports.QUEUE_ELIGIBLE = exports.QOS_PRIORITY = void 0;
|
|
18
|
+
exports.qosPriority = qosPriority;
|
|
19
|
+
exports.isQueueEligible = isQueueEligible;
|
|
20
|
+
// Lower value = higher priority. Both spellings accepted (adapter uses "best-effort").
|
|
21
|
+
exports.QOS_PRIORITY = {
|
|
22
|
+
realtime: 0,
|
|
23
|
+
interactive: 1,
|
|
24
|
+
batch: 2,
|
|
25
|
+
best_effort: 3,
|
|
26
|
+
"best-effort": 3,
|
|
27
|
+
};
|
|
28
|
+
/** Tiers that wait briefly for a slot rather than failing fast at capacity. */
|
|
29
|
+
exports.QUEUE_ELIGIBLE = new Set(["realtime", "interactive"]);
|
|
30
|
+
/** Bounded wait for queue-eligible tiers (ms). */
|
|
31
|
+
exports.QUEUE_WAIT_MS = 2000;
|
|
32
|
+
/** Priority rank for a QoS class (lower = higher priority; unknown → 3). */
|
|
33
|
+
function qosPriority(qos) {
|
|
34
|
+
if (qos == null)
|
|
35
|
+
return 3;
|
|
36
|
+
return exports.QOS_PRIORITY[qos] ?? 3;
|
|
37
|
+
}
|
|
38
|
+
/** True if a task of this QoS class should wait briefly for a slot at capacity. */
|
|
39
|
+
function isQueueEligible(qos) {
|
|
40
|
+
return qos != null && exports.QUEUE_ELIGIBLE.has(qos);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;;;;;;GAYG;;;AAkBH,kCAGC;AAGD,0CAEC;AAxBD,uFAAuF;AAC1E,QAAA,YAAY,GAA2B;IAClD,QAAQ,EAAE,CAAC;IACX,WAAW,EAAE,CAAC;IACd,KAAK,EAAE,CAAC;IACR,WAAW,EAAE,CAAC;IACd,aAAa,EAAE,CAAC;CACjB,CAAC;AAEF,+EAA+E;AAClE,QAAA,cAAc,GAAwB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;AAExF,kDAAkD;AACrC,QAAA,aAAa,GAAG,IAAI,CAAC;AAElC,4EAA4E;AAC5E,SAAgB,WAAW,CAAC,GAA8B;IACxD,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,CAAC,CAAC;IAC1B,OAAO,oBAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,mFAAmF;AACnF,SAAgB,eAAe,CAAC,GAA8B;IAC5D,OAAO,GAAG,IAAI,IAAI,IAAI,sBAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constant-time bearer-token validation (parity Block E, #340).
|
|
3
|
+
*
|
|
4
|
+
* Port of iicp-adapter `services/token_validator.py`. Compares a presented token against
|
|
5
|
+
* the expected one with `crypto.timingSafeEqual` so a timing side-channel can't recover
|
|
6
|
+
* the token byte-by-byte. The expected token is updated after registration.
|
|
7
|
+
*/
|
|
8
|
+
export declare class TokenValidator {
|
|
9
|
+
private expected;
|
|
10
|
+
constructor(expectedToken?: string);
|
|
11
|
+
isValid(presented: string | null | undefined): boolean;
|
|
12
|
+
/** Set the expected token after registration (directory-issued). */
|
|
13
|
+
updateToken(newToken: string): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=token_validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token_validator.d.ts","sourceRoot":"","sources":["../src/token_validator.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAIH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,aAAa,SAAK;IAI9B,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO;IAStD,oEAAoE;IACpE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAGpC"}
|