@holokai/neuron-sdk 0.2.0 → 0.4.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/README.md +63 -3
- package/dist/auth.d.mts +187 -0
- package/dist/auth.d.ts +187 -0
- package/dist/auth.js +354 -0
- package/dist/auth.js.map +1 -0
- package/dist/auth.mjs +343 -0
- package/dist/auth.mjs.map +1 -0
- package/dist/cli.js +436 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.mts +21 -8
- package/dist/index.d.ts +21 -8
- package/dist/index.js +100 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -29
- package/dist/index.mjs.map +1 -1
- package/dist/ipc.d.mts +1 -1
- package/dist/ipc.d.ts +1 -1
- package/dist/{transport-QqkooS7K.d.mts → transport-Cs5tY2IO.d.mts} +91 -2
- package/dist/{transport-QqkooS7K.d.ts → transport-Cs5tY2IO.d.ts} +91 -2
- package/package.json +12 -3
package/dist/index.mjs
CHANGED
|
@@ -10,6 +10,7 @@ var CapabilityTypeSchema = z.string().min(1).regex(
|
|
|
10
10
|
"capability type must be namespaced: {owner}/{package}[/{name}][.{variant}]"
|
|
11
11
|
);
|
|
12
12
|
var UserIdSchema = z.string().min(1);
|
|
13
|
+
var JsonSchemaSchema = z.unknown();
|
|
13
14
|
var CapabilityScopeSchema = z.union([
|
|
14
15
|
z.literal("any"),
|
|
15
16
|
z.object({ onBehalfOf: UserIdSchema }).strict()
|
|
@@ -18,6 +19,36 @@ var CapabilitySchema = z.object({
|
|
|
18
19
|
type: CapabilityTypeSchema,
|
|
19
20
|
scope: CapabilityScopeSchema,
|
|
20
21
|
concurrency: z.number().int().positive(),
|
|
22
|
+
/**
|
|
23
|
+
* Plain-language contract advertisement (HOL-2926). All three fields
|
|
24
|
+
* are optional and additive: older neurons keep sending
|
|
25
|
+
* `{ type, scope, concurrency }` and the gateway accepts both shapes.
|
|
26
|
+
* When present they flow (fire-and-forget) to Moku's
|
|
27
|
+
* `capability_catalog` so registry-sourced capabilities render with a
|
|
28
|
+
* real contract in the supervisor catalog instead of type-only stubs.
|
|
29
|
+
*
|
|
30
|
+
* Omit rather than null — the fields are `.optional()`, not
|
|
31
|
+
* `.nullable()`, and a `null` description fails validation.
|
|
32
|
+
*/
|
|
33
|
+
description: z.string().optional(),
|
|
34
|
+
/**
|
|
35
|
+
* JSON Schema for the capability's input payload — opaque on the wire,
|
|
36
|
+
* but `null` is rejected: the reconcile push to Moku is last-writer-wins
|
|
37
|
+
* per present key, so a null here could wipe a stored schema.
|
|
38
|
+
* (`description` already rejects null via `z.string()`.)
|
|
39
|
+
*/
|
|
40
|
+
// The `: boolean` return annotations stop TS (5.5+) from inferring the
|
|
41
|
+
// lambdas as type predicates, which would narrow the field from
|
|
42
|
+
// `unknown` to `{}` and ripple into every consumer.
|
|
43
|
+
inputSchema: JsonSchemaSchema.refine(
|
|
44
|
+
(v) => v !== null,
|
|
45
|
+
"omit inputSchema instead of sending null"
|
|
46
|
+
).optional(),
|
|
47
|
+
/** JSON Schema for the capability's output payload — same rules as inputSchema. */
|
|
48
|
+
outputSchema: JsonSchemaSchema.refine(
|
|
49
|
+
(v) => v !== null,
|
|
50
|
+
"omit outputSchema instead of sending null"
|
|
51
|
+
).optional(),
|
|
21
52
|
/**
|
|
22
53
|
* Per-capability lease TTL override in milliseconds (HOL-356).
|
|
23
54
|
* The gateway uses this when minting a lease's `expiresAt`; absent
|
|
@@ -33,7 +64,6 @@ var CapabilitySchema = z.object({
|
|
|
33
64
|
*/
|
|
34
65
|
leaseTtlMs: z.number().int().min(1e3).max(60 * 60 * 1e3).optional()
|
|
35
66
|
}).strict();
|
|
36
|
-
var JsonSchemaSchema = z.unknown();
|
|
37
67
|
var LeaseIdSchema = z.string().min(1);
|
|
38
68
|
var TaskPayloadSchema = z.object({
|
|
39
69
|
taskId: z.string().min(1),
|
|
@@ -55,9 +85,10 @@ var NeuronIdSchema = z.string().min(1);
|
|
|
55
85
|
var RegisterFrameSchema = z.object({
|
|
56
86
|
type: z.literal("register"),
|
|
57
87
|
neuronId: NeuronIdSchema,
|
|
58
|
-
// Free-form by design — the gateway
|
|
59
|
-
//
|
|
60
|
-
//
|
|
88
|
+
// Free-form by design — the gateway records this verbatim and performs
|
|
89
|
+
// no version negotiation; compatibility comes from additive-only frame
|
|
90
|
+
// evolution (see PROTOCOL_VERSION in transport.ts). Do not pin this to
|
|
91
|
+
// the exported constant.
|
|
61
92
|
protocolVersion: z.string().min(1),
|
|
62
93
|
capabilities: z.array(CapabilitySchema).min(1).refine(
|
|
63
94
|
(caps) => new Set(caps.map((c) => c.type)).size === caps.length,
|
|
@@ -171,7 +202,7 @@ z.discriminatedUnion("type", [
|
|
|
171
202
|
]);
|
|
172
203
|
|
|
173
204
|
// ../neuron-protocol/src/transport.ts
|
|
174
|
-
var PROTOCOL_VERSION = "1.
|
|
205
|
+
var PROTOCOL_VERSION = "1.1.0";
|
|
175
206
|
var SSE_PATH = "/neuron/events";
|
|
176
207
|
var SSE_EVENT = {
|
|
177
208
|
registered: "registered",
|
|
@@ -226,6 +257,12 @@ function toRegistrationCapability(def, opts) {
|
|
|
226
257
|
type: def.type,
|
|
227
258
|
scope,
|
|
228
259
|
concurrency,
|
|
260
|
+
// Contract advertisement (HOL-2926). `description` is required on the
|
|
261
|
+
// def, so it is always present here; `opts.description` lets a
|
|
262
|
+
// deployment reword it without redefining the capability.
|
|
263
|
+
description: opts?.description ?? def.description,
|
|
264
|
+
inputSchema: def.inputSchema,
|
|
265
|
+
outputSchema: def.outputSchema,
|
|
229
266
|
...typeof leaseTtlMs === "number" ? { leaseTtlMs } : {}
|
|
230
267
|
};
|
|
231
268
|
}
|
|
@@ -245,7 +282,6 @@ var HeartbeatLoop = class {
|
|
|
245
282
|
this.timer = setInterval(() => {
|
|
246
283
|
void this.tick();
|
|
247
284
|
}, this.intervalMs);
|
|
248
|
-
if (typeof this.timer.unref === "function") this.timer.unref();
|
|
249
285
|
}
|
|
250
286
|
stop() {
|
|
251
287
|
if (this.timer) {
|
|
@@ -496,9 +532,6 @@ var HttpTransport = class {
|
|
|
496
532
|
this.reconnectTimer = null;
|
|
497
533
|
void this.openStream();
|
|
498
534
|
}, delay);
|
|
499
|
-
if (typeof this.reconnectTimer === "object" && this.reconnectTimer !== null && "unref" in this.reconnectTimer && typeof this.reconnectTimer.unref === "function") {
|
|
500
|
-
this.reconnectTimer.unref();
|
|
501
|
-
}
|
|
502
535
|
}
|
|
503
536
|
};
|
|
504
537
|
var TransportError = class extends Error {
|
|
@@ -530,8 +563,19 @@ function validateInput(zod, validator, jsonSchema, data) {
|
|
|
530
563
|
return errors === null ? { ok: true, value: data } : { ok: false, errors };
|
|
531
564
|
}
|
|
532
565
|
async function runLease(opts) {
|
|
533
|
-
const {
|
|
534
|
-
|
|
566
|
+
const {
|
|
567
|
+
lease,
|
|
568
|
+
handler,
|
|
569
|
+
zodInput,
|
|
570
|
+
zodOutput,
|
|
571
|
+
inputSchema,
|
|
572
|
+
outputSchema,
|
|
573
|
+
transport,
|
|
574
|
+
validator,
|
|
575
|
+
logger,
|
|
576
|
+
signal
|
|
577
|
+
} = opts;
|
|
578
|
+
const inputCheck = validateInput(zodInput, validator, inputSchema, lease.task.input);
|
|
535
579
|
if (!inputCheck.ok) {
|
|
536
580
|
await sendNack(
|
|
537
581
|
transport,
|
|
@@ -593,7 +637,7 @@ async function runLease(opts) {
|
|
|
593
637
|
);
|
|
594
638
|
return;
|
|
595
639
|
}
|
|
596
|
-
const outputCheck = validateInput(zodOutput, validator,
|
|
640
|
+
const outputCheck = validateInput(zodOutput, validator, outputSchema, output);
|
|
597
641
|
if (!outputCheck.ok) {
|
|
598
642
|
await sendNack(
|
|
599
643
|
transport,
|
|
@@ -660,32 +704,39 @@ function scopedLogger(logger, lease) {
|
|
|
660
704
|
var Ajv = AjvDefault.default ?? AjvDefault;
|
|
661
705
|
var addFormats = addFormatsDefault.default ?? addFormatsDefault;
|
|
662
706
|
var SchemaValidator = class {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
constructor() {
|
|
707
|
+
constructor(onCompileError) {
|
|
708
|
+
this.onCompileError = onCompileError;
|
|
666
709
|
this.ajv = new Ajv({ allErrors: true, strict: false });
|
|
667
710
|
addFormats(this.ajv);
|
|
668
711
|
}
|
|
712
|
+
ajv;
|
|
713
|
+
cache = /* @__PURE__ */ new WeakMap();
|
|
714
|
+
// Schemas whose compilation threw. Cannot-compile is an environment or
|
|
715
|
+
// schema-authoring problem, not evidence about the data — so validate()
|
|
716
|
+
// FAILS OPEN for these (returns null) instead of reporting a mismatch.
|
|
717
|
+
// Nacking on compile failure turned every lease into an
|
|
718
|
+
// INPUT_SCHEMA_MISMATCH retry loop on runtimes where ajv's codegen is
|
|
719
|
+
// unavailable (Electron renderers with CSP `script-src 'self'` block
|
|
720
|
+
// `new Function`) — HOL-2937.
|
|
721
|
+
uncompilable = /* @__PURE__ */ new WeakSet();
|
|
669
722
|
/**
|
|
670
|
-
* Returns null if the value matches the schema
|
|
671
|
-
*
|
|
723
|
+
* Returns null if the value matches the schema, no schema was given, or
|
|
724
|
+
* the schema cannot be compiled in this runtime (fail-open — the gateway
|
|
725
|
+
* remains the enforcement point); otherwise an array of structured errors.
|
|
672
726
|
*/
|
|
673
727
|
validate(schema, data) {
|
|
674
728
|
if (!schema || typeof schema !== "object") return null;
|
|
729
|
+
if (this.uncompilable.has(schema)) return null;
|
|
675
730
|
let validator = this.cache.get(schema);
|
|
676
731
|
if (!validator) {
|
|
677
732
|
try {
|
|
678
733
|
validator = this.ajv.compile(schema);
|
|
679
734
|
} catch (err) {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
params: {},
|
|
686
|
-
message: `schema failed to compile: ${err instanceof Error ? err.message : String(err)}`
|
|
687
|
-
}
|
|
688
|
-
];
|
|
735
|
+
this.uncompilable.add(schema);
|
|
736
|
+
this.onCompileError?.(
|
|
737
|
+
`schema failed to compile \u2014 skipping SDK-side validation for this schema: ${err instanceof Error ? err.message : String(err)}`
|
|
738
|
+
);
|
|
739
|
+
return null;
|
|
689
740
|
}
|
|
690
741
|
this.cache.set(schema, validator);
|
|
691
742
|
}
|
|
@@ -818,7 +869,9 @@ var Neuron = class extends EventEmitter {
|
|
|
818
869
|
super();
|
|
819
870
|
this.logger = opts.logger ?? noopLogger;
|
|
820
871
|
this.neuronId = opts.neuronId;
|
|
821
|
-
this.validator = new SchemaValidator(
|
|
872
|
+
this.validator = new SchemaValidator(
|
|
873
|
+
(message) => this.logger.warn({ neuronId: this.neuronId }, message)
|
|
874
|
+
);
|
|
822
875
|
this.transport = isWithTransport(opts) ? opts.transport : new HttpTransport({
|
|
823
876
|
gatewayUrl: opts.gatewayUrl,
|
|
824
877
|
neuronId: opts.neuronId,
|
|
@@ -890,7 +943,15 @@ var Neuron = class extends EventEmitter {
|
|
|
890
943
|
);
|
|
891
944
|
}
|
|
892
945
|
handler = optsOrHandler;
|
|
893
|
-
capability = {
|
|
946
|
+
capability = {
|
|
947
|
+
type: reg.type,
|
|
948
|
+
scope: reg.scope,
|
|
949
|
+
concurrency: reg.concurrency,
|
|
950
|
+
...reg.description !== void 0 ? { description: reg.description } : {},
|
|
951
|
+
...reg.inputSchema !== void 0 ? { inputSchema: reg.inputSchema } : {},
|
|
952
|
+
...reg.outputSchema !== void 0 ? { outputSchema: reg.outputSchema } : {},
|
|
953
|
+
...typeof reg.leaseTtlMs === "number" ? { leaseTtlMs: reg.leaseTtlMs } : {}
|
|
954
|
+
};
|
|
894
955
|
inputSchema = reg.inputSchema;
|
|
895
956
|
outputSchema = reg.outputSchema;
|
|
896
957
|
}
|
|
@@ -1001,7 +1062,15 @@ var Neuron = class extends EventEmitter {
|
|
|
1001
1062
|
this.hasOpenedOnce = true;
|
|
1002
1063
|
this.heartbeat.start();
|
|
1003
1064
|
} catch (err) {
|
|
1004
|
-
|
|
1065
|
+
const cause = err instanceof Error ? err : new Error(String(err));
|
|
1066
|
+
this.logger.error(
|
|
1067
|
+
{ err: cause },
|
|
1068
|
+
"register POST rejected; SSE is open but the neuron is NOT registered and will receive no leases"
|
|
1069
|
+
);
|
|
1070
|
+
this.emit(
|
|
1071
|
+
"error",
|
|
1072
|
+
new Error(`registration rejected by gateway: ${cause.message}`, { cause })
|
|
1073
|
+
);
|
|
1005
1074
|
}
|
|
1006
1075
|
}
|
|
1007
1076
|
handleConnectionClose(reason) {
|
|
@@ -1078,6 +1147,8 @@ var Neuron = class extends EventEmitter {
|
|
|
1078
1147
|
handler: handler.handler,
|
|
1079
1148
|
zodInput: handler.zodInput,
|
|
1080
1149
|
zodOutput: handler.zodOutput,
|
|
1150
|
+
inputSchema: handler.inputSchema,
|
|
1151
|
+
outputSchema: handler.outputSchema,
|
|
1081
1152
|
transport: this.transport,
|
|
1082
1153
|
validator: this.validator,
|
|
1083
1154
|
logger: this.logger,
|