@holokai/neuron-sdk 0.1.0 → 0.2.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/LICENSE +21 -0
- package/README.md +246 -14
- package/dist/index.d.mts +54 -668
- package/dist/index.d.ts +54 -668
- package/dist/index.js +227 -209
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +227 -209
- package/dist/index.mjs.map +1 -1
- package/dist/ipc.d.mts +88 -0
- package/dist/ipc.d.ts +88 -0
- package/dist/ipc.js +86 -0
- package/dist/ipc.js.map +1 -0
- package/dist/ipc.mjs +84 -0
- package/dist/ipc.mjs.map +1 -0
- package/dist/transport-QqkooS7K.d.mts +742 -0
- package/dist/transport-QqkooS7K.d.ts +742 -0
- package/package.json +15 -6
package/dist/index.js
CHANGED
|
@@ -24,7 +24,21 @@ var CapabilityScopeSchema = zod.z.union([
|
|
|
24
24
|
var CapabilitySchema = zod.z.object({
|
|
25
25
|
type: CapabilityTypeSchema,
|
|
26
26
|
scope: CapabilityScopeSchema,
|
|
27
|
-
concurrency: zod.z.number().int().positive()
|
|
27
|
+
concurrency: zod.z.number().int().positive(),
|
|
28
|
+
/**
|
|
29
|
+
* Per-capability lease TTL override in milliseconds (HOL-356).
|
|
30
|
+
* The gateway uses this when minting a lease's `expiresAt`; absent
|
|
31
|
+
* → falls back to the gateway's default (`leaseTtlMs` on the
|
|
32
|
+
* dispatcher). Lets a slow capability (e.g. a scripted run with a
|
|
33
|
+
* 10-minute deadline) declare a longer TTL without tuning the
|
|
34
|
+
* whole gateway.
|
|
35
|
+
*
|
|
36
|
+
* Bounded by reasonable extremes: at least 1s (anything shorter
|
|
37
|
+
* than a heartbeat is meaningless) and at most 1h (the reaper +
|
|
38
|
+
* heartbeat budget should be the limiter, not a single
|
|
39
|
+
* capability).
|
|
40
|
+
*/
|
|
41
|
+
leaseTtlMs: zod.z.number().int().min(1e3).max(60 * 60 * 1e3).optional()
|
|
28
42
|
}).strict();
|
|
29
43
|
var JsonSchemaSchema = zod.z.unknown();
|
|
30
44
|
var LeaseIdSchema = zod.z.string().min(1);
|
|
@@ -189,6 +203,7 @@ function defineCapability(init) {
|
|
|
189
203
|
outputSchema: zodToJsonSchema.zodToJsonSchema(init.output, { $refStrategy: "none" }),
|
|
190
204
|
scope: init.scope,
|
|
191
205
|
concurrency: init.concurrency,
|
|
206
|
+
leaseTtlMs: init.leaseTtlMs,
|
|
192
207
|
_zod: { input: init.input, output: init.output }
|
|
193
208
|
};
|
|
194
209
|
}
|
|
@@ -213,7 +228,13 @@ function toRegistrationCapability(def, opts) {
|
|
|
213
228
|
`capability ${def.type}: concurrency is required for registration \u2014 set it on defineCapability(...) or at neuron.handle(def, { concurrency }, fn)`
|
|
214
229
|
);
|
|
215
230
|
}
|
|
216
|
-
|
|
231
|
+
const leaseTtlMs = opts?.leaseTtlMs ?? def.leaseTtlMs;
|
|
232
|
+
return {
|
|
233
|
+
type: def.type,
|
|
234
|
+
scope,
|
|
235
|
+
concurrency,
|
|
236
|
+
...typeof leaseTtlMs === "number" ? { leaseTtlMs } : {}
|
|
237
|
+
};
|
|
217
238
|
}
|
|
218
239
|
|
|
219
240
|
// src/heartbeat.ts
|
|
@@ -259,155 +280,6 @@ var HeartbeatLoop = class {
|
|
|
259
280
|
}
|
|
260
281
|
};
|
|
261
282
|
|
|
262
|
-
// src/lease-runner.ts
|
|
263
|
-
var TerminalFailure = class extends Error {
|
|
264
|
-
constructor(reason, code) {
|
|
265
|
-
super(reason);
|
|
266
|
-
this.reason = reason;
|
|
267
|
-
this.code = code;
|
|
268
|
-
this.name = "TerminalFailure";
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
function validateInput(zod, validator, jsonSchema, data) {
|
|
272
|
-
if (zod) {
|
|
273
|
-
const result = zod.safeParse(data);
|
|
274
|
-
return result.success ? { ok: true, value: result.data } : { ok: false, errors: result.error.issues };
|
|
275
|
-
}
|
|
276
|
-
const errors = validator.validate(
|
|
277
|
-
jsonSchema,
|
|
278
|
-
data
|
|
279
|
-
);
|
|
280
|
-
return errors === null ? { ok: true, value: data } : { ok: false, errors };
|
|
281
|
-
}
|
|
282
|
-
async function runLease(opts) {
|
|
283
|
-
const { lease, handler, zodInput, zodOutput, transport, validator, logger, signal } = opts;
|
|
284
|
-
const inputCheck = validateInput(zodInput, validator, lease.inputSchema, lease.task.input);
|
|
285
|
-
if (!inputCheck.ok) {
|
|
286
|
-
await sendNack(
|
|
287
|
-
transport,
|
|
288
|
-
lease.leaseId,
|
|
289
|
-
"schema-mismatch",
|
|
290
|
-
"lease input does not match inputSchema",
|
|
291
|
-
{ code: "INPUT_SCHEMA_MISMATCH", details: { errors: inputCheck.errors } },
|
|
292
|
-
logger
|
|
293
|
-
);
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const parsedInput = inputCheck.value;
|
|
297
|
-
const progressFn = makeProgressFn(transport, lease.leaseId, logger);
|
|
298
|
-
const ctx = {
|
|
299
|
-
task: lease.task,
|
|
300
|
-
leaseId: lease.leaseId,
|
|
301
|
-
signal,
|
|
302
|
-
log: scopedLogger(logger, lease),
|
|
303
|
-
progress: progressFn,
|
|
304
|
-
fail: (reason, opts2) => {
|
|
305
|
-
throw new TerminalFailure(reason, opts2?.code);
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
let output;
|
|
309
|
-
try {
|
|
310
|
-
output = await handler(parsedInput, ctx);
|
|
311
|
-
} catch (err) {
|
|
312
|
-
if (signal.aborted || err.name === "AbortError") {
|
|
313
|
-
await sendNack(
|
|
314
|
-
transport,
|
|
315
|
-
lease.leaseId,
|
|
316
|
-
"cancelled",
|
|
317
|
-
"handler aborted",
|
|
318
|
-
{ code: "CANCELLED" },
|
|
319
|
-
logger
|
|
320
|
-
);
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
if (err instanceof TerminalFailure) {
|
|
324
|
-
await sendNack(
|
|
325
|
-
transport,
|
|
326
|
-
lease.leaseId,
|
|
327
|
-
"terminal",
|
|
328
|
-
err.reason,
|
|
329
|
-
{ code: err.code ?? "HANDLER_TERMINAL" },
|
|
330
|
-
logger
|
|
331
|
-
);
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
335
|
-
logger.error({ err, leaseId: lease.leaseId }, "handler threw; nacking retryable");
|
|
336
|
-
await sendNack(
|
|
337
|
-
transport,
|
|
338
|
-
lease.leaseId,
|
|
339
|
-
"retryable",
|
|
340
|
-
message,
|
|
341
|
-
{ code: "HANDLER_THREW" },
|
|
342
|
-
logger
|
|
343
|
-
);
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
const outputCheck = validateInput(zodOutput, validator, lease.outputSchema, output);
|
|
347
|
-
if (!outputCheck.ok) {
|
|
348
|
-
await sendNack(
|
|
349
|
-
transport,
|
|
350
|
-
lease.leaseId,
|
|
351
|
-
"schema-mismatch",
|
|
352
|
-
"handler output does not match outputSchema",
|
|
353
|
-
{ code: "OUTPUT_SCHEMA_MISMATCH", details: { errors: outputCheck.errors } },
|
|
354
|
-
logger
|
|
355
|
-
);
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
const parsedOutput = outputCheck.value;
|
|
359
|
-
await transport.post(POST_PATH.ack, {
|
|
360
|
-
type: "ack",
|
|
361
|
-
leaseId: lease.leaseId,
|
|
362
|
-
output: parsedOutput,
|
|
363
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
364
|
-
}).catch((err) => {
|
|
365
|
-
logger.warn(
|
|
366
|
-
{ err, leaseId: lease.leaseId },
|
|
367
|
-
"ack POST rejected by gateway; lease will be reclaimed by reaper"
|
|
368
|
-
);
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
async function sendNack(transport, leaseId, kind, reason, extras = {}, logger) {
|
|
372
|
-
await transport.post(POST_PATH.nack, {
|
|
373
|
-
type: "nack",
|
|
374
|
-
leaseId,
|
|
375
|
-
kind,
|
|
376
|
-
reason,
|
|
377
|
-
code: extras.code,
|
|
378
|
-
details: extras.details,
|
|
379
|
-
failedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
380
|
-
}).catch((err) => {
|
|
381
|
-
logger?.warn(
|
|
382
|
-
{ err, leaseId, kind },
|
|
383
|
-
"nack POST rejected by gateway; lease will be reclaimed by reaper"
|
|
384
|
-
);
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
function makeProgressFn(transport, leaseId, logger) {
|
|
388
|
-
return (update) => {
|
|
389
|
-
void transport.post(POST_PATH.progress, {
|
|
390
|
-
type: "progress",
|
|
391
|
-
leaseId,
|
|
392
|
-
percent: update.percent,
|
|
393
|
-
message: update.message,
|
|
394
|
-
data: update.data,
|
|
395
|
-
sentAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
396
|
-
}).catch((err) => {
|
|
397
|
-
logger.warn({ err, leaseId }, "progress POST failed; continuing");
|
|
398
|
-
});
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
|
-
function scopedLogger(logger, lease) {
|
|
402
|
-
const scope = { leaseId: lease.leaseId, taskId: lease.task.taskId };
|
|
403
|
-
return {
|
|
404
|
-
debug: (meta, msg) => logger.debug({ ...scope, ...meta }, msg),
|
|
405
|
-
info: (meta, msg) => logger.info({ ...scope, ...meta }, msg),
|
|
406
|
-
warn: (meta, msg) => logger.warn({ ...scope, ...meta }, msg),
|
|
407
|
-
error: (meta, msg) => logger.error({ ...scope, ...meta }, msg)
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
|
|
411
283
|
// src/logger.ts
|
|
412
284
|
var noopLogger = {
|
|
413
285
|
debug() {
|
|
@@ -419,43 +291,6 @@ var noopLogger = {
|
|
|
419
291
|
error() {
|
|
420
292
|
}
|
|
421
293
|
};
|
|
422
|
-
var Ajv = AjvDefault__default.default.default ?? AjvDefault__default.default;
|
|
423
|
-
var addFormats = addFormatsDefault__default.default.default ?? addFormatsDefault__default.default;
|
|
424
|
-
var SchemaValidator = class {
|
|
425
|
-
ajv;
|
|
426
|
-
cache = /* @__PURE__ */ new WeakMap();
|
|
427
|
-
constructor() {
|
|
428
|
-
this.ajv = new Ajv({ allErrors: true, strict: false });
|
|
429
|
-
addFormats(this.ajv);
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Returns null if the value matches the schema (or no schema given);
|
|
433
|
-
* otherwise an array of structured errors.
|
|
434
|
-
*/
|
|
435
|
-
validate(schema, data) {
|
|
436
|
-
if (!schema || typeof schema !== "object") return null;
|
|
437
|
-
let validator = this.cache.get(schema);
|
|
438
|
-
if (!validator) {
|
|
439
|
-
try {
|
|
440
|
-
validator = this.ajv.compile(schema);
|
|
441
|
-
} catch (err) {
|
|
442
|
-
return [
|
|
443
|
-
{
|
|
444
|
-
instancePath: "",
|
|
445
|
-
schemaPath: "",
|
|
446
|
-
keyword: "schema",
|
|
447
|
-
params: {},
|
|
448
|
-
message: `schema failed to compile: ${err instanceof Error ? err.message : String(err)}`
|
|
449
|
-
}
|
|
450
|
-
];
|
|
451
|
-
}
|
|
452
|
-
this.cache.set(schema, validator);
|
|
453
|
-
}
|
|
454
|
-
const v = validator;
|
|
455
|
-
const ok = v(data);
|
|
456
|
-
return ok ? null : v.errors ?? [];
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
294
|
|
|
460
295
|
// src/sse-parser.ts
|
|
461
296
|
async function* parseSSEStream(stream, signal) {
|
|
@@ -505,10 +340,10 @@ function parseBlock(block) {
|
|
|
505
340
|
return { event, data: dataLines.join("\n") };
|
|
506
341
|
}
|
|
507
342
|
|
|
508
|
-
// src/transport.ts
|
|
509
|
-
var
|
|
343
|
+
// src/http-transport.ts
|
|
344
|
+
var HttpTransport = class {
|
|
510
345
|
opts;
|
|
511
|
-
callbacks;
|
|
346
|
+
callbacks = {};
|
|
512
347
|
abortController = null;
|
|
513
348
|
stopped = false;
|
|
514
349
|
connected = false;
|
|
@@ -524,13 +359,9 @@ var Transport = class {
|
|
|
524
359
|
logger: opts.logger ?? noopLogger,
|
|
525
360
|
fetch: opts.fetch ?? globalThis.fetch.bind(globalThis)
|
|
526
361
|
};
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
onFrame: opts.onFrame,
|
|
531
|
-
onError: opts.onError,
|
|
532
|
-
onReconnecting: opts.onReconnecting
|
|
533
|
-
};
|
|
362
|
+
}
|
|
363
|
+
subscribe(callbacks) {
|
|
364
|
+
this.callbacks = callbacks;
|
|
534
365
|
}
|
|
535
366
|
isConnected() {
|
|
536
367
|
return this.connected;
|
|
@@ -685,6 +516,192 @@ var TransportError = class extends Error {
|
|
|
685
516
|
}
|
|
686
517
|
};
|
|
687
518
|
|
|
519
|
+
// src/lease-runner.ts
|
|
520
|
+
var TerminalFailure = class extends Error {
|
|
521
|
+
constructor(reason, code) {
|
|
522
|
+
super(reason);
|
|
523
|
+
this.reason = reason;
|
|
524
|
+
this.code = code;
|
|
525
|
+
this.name = "TerminalFailure";
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
function validateInput(zod, validator, jsonSchema, data) {
|
|
529
|
+
if (zod) {
|
|
530
|
+
const result = zod.safeParse(data);
|
|
531
|
+
return result.success ? { ok: true, value: result.data } : { ok: false, errors: result.error.issues };
|
|
532
|
+
}
|
|
533
|
+
const errors = validator.validate(
|
|
534
|
+
jsonSchema,
|
|
535
|
+
data
|
|
536
|
+
);
|
|
537
|
+
return errors === null ? { ok: true, value: data } : { ok: false, errors };
|
|
538
|
+
}
|
|
539
|
+
async function runLease(opts) {
|
|
540
|
+
const { lease, handler, zodInput, zodOutput, transport, validator, logger, signal } = opts;
|
|
541
|
+
const inputCheck = validateInput(zodInput, validator, lease.inputSchema, lease.task.input);
|
|
542
|
+
if (!inputCheck.ok) {
|
|
543
|
+
await sendNack(
|
|
544
|
+
transport,
|
|
545
|
+
lease.leaseId,
|
|
546
|
+
"schema-mismatch",
|
|
547
|
+
"lease input does not match inputSchema",
|
|
548
|
+
{ code: "INPUT_SCHEMA_MISMATCH", details: { errors: inputCheck.errors } },
|
|
549
|
+
logger
|
|
550
|
+
);
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
const parsedInput = inputCheck.value;
|
|
554
|
+
const progressFn = makeProgressFn(transport, lease.leaseId, logger);
|
|
555
|
+
const ctx = {
|
|
556
|
+
task: lease.task,
|
|
557
|
+
leaseId: lease.leaseId,
|
|
558
|
+
signal,
|
|
559
|
+
log: scopedLogger(logger, lease),
|
|
560
|
+
progress: progressFn,
|
|
561
|
+
fail: (reason, opts2) => {
|
|
562
|
+
throw new TerminalFailure(reason, opts2?.code);
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
let output;
|
|
566
|
+
try {
|
|
567
|
+
output = await handler(parsedInput, ctx);
|
|
568
|
+
} catch (err) {
|
|
569
|
+
if (signal.aborted || err.name === "AbortError") {
|
|
570
|
+
await sendNack(
|
|
571
|
+
transport,
|
|
572
|
+
lease.leaseId,
|
|
573
|
+
"cancelled",
|
|
574
|
+
"handler aborted",
|
|
575
|
+
{ code: "CANCELLED" },
|
|
576
|
+
logger
|
|
577
|
+
);
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
if (err instanceof TerminalFailure) {
|
|
581
|
+
await sendNack(
|
|
582
|
+
transport,
|
|
583
|
+
lease.leaseId,
|
|
584
|
+
"terminal",
|
|
585
|
+
err.reason,
|
|
586
|
+
{ code: err.code ?? "HANDLER_TERMINAL" },
|
|
587
|
+
logger
|
|
588
|
+
);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
592
|
+
logger.error({ err, leaseId: lease.leaseId }, "handler threw; nacking retryable");
|
|
593
|
+
await sendNack(
|
|
594
|
+
transport,
|
|
595
|
+
lease.leaseId,
|
|
596
|
+
"retryable",
|
|
597
|
+
message,
|
|
598
|
+
{ code: "HANDLER_THREW" },
|
|
599
|
+
logger
|
|
600
|
+
);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const outputCheck = validateInput(zodOutput, validator, lease.outputSchema, output);
|
|
604
|
+
if (!outputCheck.ok) {
|
|
605
|
+
await sendNack(
|
|
606
|
+
transport,
|
|
607
|
+
lease.leaseId,
|
|
608
|
+
"schema-mismatch",
|
|
609
|
+
"handler output does not match outputSchema",
|
|
610
|
+
{ code: "OUTPUT_SCHEMA_MISMATCH", details: { errors: outputCheck.errors } },
|
|
611
|
+
logger
|
|
612
|
+
);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const parsedOutput = outputCheck.value;
|
|
616
|
+
await transport.post(POST_PATH.ack, {
|
|
617
|
+
type: "ack",
|
|
618
|
+
leaseId: lease.leaseId,
|
|
619
|
+
output: parsedOutput,
|
|
620
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
621
|
+
}).catch((err) => {
|
|
622
|
+
logger.warn(
|
|
623
|
+
{ err, leaseId: lease.leaseId },
|
|
624
|
+
"ack POST rejected by gateway; lease will be reclaimed by reaper"
|
|
625
|
+
);
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
async function sendNack(transport, leaseId, kind, reason, extras = {}, logger) {
|
|
629
|
+
await transport.post(POST_PATH.nack, {
|
|
630
|
+
type: "nack",
|
|
631
|
+
leaseId,
|
|
632
|
+
kind,
|
|
633
|
+
reason,
|
|
634
|
+
code: extras.code,
|
|
635
|
+
details: extras.details,
|
|
636
|
+
failedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
637
|
+
}).catch((err) => {
|
|
638
|
+
logger?.warn(
|
|
639
|
+
{ err, leaseId, kind },
|
|
640
|
+
"nack POST rejected by gateway; lease will be reclaimed by reaper"
|
|
641
|
+
);
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
function makeProgressFn(transport, leaseId, logger) {
|
|
645
|
+
return (update) => {
|
|
646
|
+
void transport.post(POST_PATH.progress, {
|
|
647
|
+
type: "progress",
|
|
648
|
+
leaseId,
|
|
649
|
+
percent: update.percent,
|
|
650
|
+
message: update.message,
|
|
651
|
+
data: update.data,
|
|
652
|
+
sentAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
653
|
+
}).catch((err) => {
|
|
654
|
+
logger.warn({ err, leaseId }, "progress POST failed; continuing");
|
|
655
|
+
});
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function scopedLogger(logger, lease) {
|
|
659
|
+
const scope = { leaseId: lease.leaseId, taskId: lease.task.taskId };
|
|
660
|
+
return {
|
|
661
|
+
debug: (meta, msg) => logger.debug({ ...scope, ...meta }, msg),
|
|
662
|
+
info: (meta, msg) => logger.info({ ...scope, ...meta }, msg),
|
|
663
|
+
warn: (meta, msg) => logger.warn({ ...scope, ...meta }, msg),
|
|
664
|
+
error: (meta, msg) => logger.error({ ...scope, ...meta }, msg)
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
var Ajv = AjvDefault__default.default.default ?? AjvDefault__default.default;
|
|
668
|
+
var addFormats = addFormatsDefault__default.default.default ?? addFormatsDefault__default.default;
|
|
669
|
+
var SchemaValidator = class {
|
|
670
|
+
ajv;
|
|
671
|
+
cache = /* @__PURE__ */ new WeakMap();
|
|
672
|
+
constructor() {
|
|
673
|
+
this.ajv = new Ajv({ allErrors: true, strict: false });
|
|
674
|
+
addFormats(this.ajv);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Returns null if the value matches the schema (or no schema given);
|
|
678
|
+
* otherwise an array of structured errors.
|
|
679
|
+
*/
|
|
680
|
+
validate(schema, data) {
|
|
681
|
+
if (!schema || typeof schema !== "object") return null;
|
|
682
|
+
let validator = this.cache.get(schema);
|
|
683
|
+
if (!validator) {
|
|
684
|
+
try {
|
|
685
|
+
validator = this.ajv.compile(schema);
|
|
686
|
+
} catch (err) {
|
|
687
|
+
return [
|
|
688
|
+
{
|
|
689
|
+
instancePath: "",
|
|
690
|
+
schemaPath: "",
|
|
691
|
+
keyword: "schema",
|
|
692
|
+
params: {},
|
|
693
|
+
message: `schema failed to compile: ${err instanceof Error ? err.message : String(err)}`
|
|
694
|
+
}
|
|
695
|
+
];
|
|
696
|
+
}
|
|
697
|
+
this.cache.set(schema, validator);
|
|
698
|
+
}
|
|
699
|
+
const v = validator;
|
|
700
|
+
const ok = v(data);
|
|
701
|
+
return ok ? null : v.errors ?? [];
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
|
|
688
705
|
// src/worker-pool.ts
|
|
689
706
|
var WorkerPool = class {
|
|
690
707
|
constructor(maxConcurrency) {
|
|
@@ -784,6 +801,9 @@ var ShutdownError = class extends Error {
|
|
|
784
801
|
};
|
|
785
802
|
|
|
786
803
|
// src/neuron.ts
|
|
804
|
+
function isWithTransport(opts) {
|
|
805
|
+
return "transport" in opts && opts.transport !== void 0;
|
|
806
|
+
}
|
|
787
807
|
var Neuron = class extends eventemitter3.EventEmitter {
|
|
788
808
|
transport;
|
|
789
809
|
handlers = /* @__PURE__ */ new Map();
|
|
@@ -797,27 +817,25 @@ var Neuron = class extends eventemitter3.EventEmitter {
|
|
|
797
817
|
heartbeat;
|
|
798
818
|
validator;
|
|
799
819
|
logger;
|
|
800
|
-
|
|
820
|
+
neuronId;
|
|
801
821
|
started = false;
|
|
802
822
|
stopping = false;
|
|
803
823
|
hasOpenedOnce = false;
|
|
804
824
|
constructor(opts) {
|
|
805
825
|
super();
|
|
806
|
-
this.opts = opts;
|
|
807
826
|
this.logger = opts.logger ?? noopLogger;
|
|
827
|
+
this.neuronId = opts.neuronId;
|
|
808
828
|
this.validator = new SchemaValidator();
|
|
809
|
-
this.transport = new
|
|
829
|
+
this.transport = isWithTransport(opts) ? opts.transport : new HttpTransport({
|
|
810
830
|
gatewayUrl: opts.gatewayUrl,
|
|
811
831
|
neuronId: opts.neuronId,
|
|
812
832
|
auth: opts.auth,
|
|
813
833
|
logger: this.logger,
|
|
814
834
|
initialReconnectDelayMs: opts.initialReconnectDelayMs,
|
|
815
835
|
maxReconnectDelayMs: opts.maxReconnectDelayMs,
|
|
816
|
-
fetch: opts.fetch
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
// event emitter. The Neuron is the one that re-publishes lifecycle
|
|
820
|
-
// signals to its own consumers via the public emitter.
|
|
836
|
+
fetch: opts.fetch
|
|
837
|
+
});
|
|
838
|
+
this.transport.subscribe({
|
|
821
839
|
onOpen: () => {
|
|
822
840
|
this.emit("connection:open");
|
|
823
841
|
void this.handleConnectionOpen();
|
|
@@ -911,7 +929,7 @@ var Neuron = class extends eventemitter3.EventEmitter {
|
|
|
911
929
|
if (this.started && this.transport.isConnected()) {
|
|
912
930
|
await this.transport.post(POST_PATH.updateCapability, {
|
|
913
931
|
type: "update-capability",
|
|
914
|
-
neuronId: this.
|
|
932
|
+
neuronId: this.neuronId,
|
|
915
933
|
capability: entry.capability
|
|
916
934
|
}).catch((err) => {
|
|
917
935
|
this.logger.warn(
|
|
@@ -1000,7 +1018,7 @@ var Neuron = class extends eventemitter3.EventEmitter {
|
|
|
1000
1018
|
async postRegister() {
|
|
1001
1019
|
await this.transport.post(POST_PATH.register, {
|
|
1002
1020
|
type: "register",
|
|
1003
|
-
neuronId: this.
|
|
1021
|
+
neuronId: this.neuronId,
|
|
1004
1022
|
protocolVersion: PROTOCOL_VERSION,
|
|
1005
1023
|
capabilities: Array.from(this.handlers.values()).map((h) => h.capability)
|
|
1006
1024
|
});
|
|
@@ -1110,11 +1128,11 @@ var Neuron = class extends eventemitter3.EventEmitter {
|
|
|
1110
1128
|
};
|
|
1111
1129
|
var SSE_EVENT_NAMES = SSE_EVENT;
|
|
1112
1130
|
|
|
1131
|
+
exports.HttpTransport = HttpTransport;
|
|
1113
1132
|
exports.Neuron = Neuron;
|
|
1114
1133
|
exports.SSE_EVENT_NAMES = SSE_EVENT_NAMES;
|
|
1115
1134
|
exports.SchemaValidator = SchemaValidator;
|
|
1116
1135
|
exports.ShutdownError = ShutdownError;
|
|
1117
|
-
exports.Transport = Transport;
|
|
1118
1136
|
exports.TransportError = TransportError;
|
|
1119
1137
|
exports.WorkerPool = WorkerPool;
|
|
1120
1138
|
exports.defineCapability = defineCapability;
|