@lifesi/genesis 0.0.0-stage → 0.1.1
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/beacons.d.ts +19 -0
- package/dist/beacons.js +10 -0
- package/dist/client.d.ts +8261 -0
- package/dist/client.js +179 -0
- package/dist/dials.d.ts +129 -0
- package/dist/dials.js +59 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.js +35 -0
- package/dist/fleets.d.ts +71 -0
- package/dist/fleets.js +44 -0
- package/dist/generated/operations.d.ts +8216 -0
- package/dist/generated/operations.js +9657 -0
- package/dist/generated/schema.d.ts +12834 -0
- package/dist/generated/schema.js +1 -0
- package/dist/genesis.d.ts +830 -0
- package/dist/genesis.js +136 -0
- package/dist/genesis.openapi.json +18131 -0
- package/dist/henry.d.ts +155 -0
- package/dist/henry.js +14 -0
- package/dist/hives-functions.d.ts +15 -0
- package/dist/hives-functions.js +94 -0
- package/dist/hives-node.d.ts +9 -0
- package/dist/hives-node.js +150 -0
- package/dist/hives-response.d.ts +2 -0
- package/dist/hives-response.js +32 -0
- package/dist/hives-upload.d.ts +9 -0
- package/dist/hives-upload.js +23 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +10 -0
- package/dist/runner.d.ts +52 -0
- package/dist/runner.js +112 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.js +1 -0
- package/package.json +26 -3
- package/README.md +0 -3
package/dist/runner.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const requestOptions = (options) => ({ signal: options.signal });
|
|
2
|
+
const opaqueId = (v) => typeof v === 'string' && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(v);
|
|
3
|
+
const pathLike = (v) => /^[A-Za-z]:/.test(v) || v.includes('..');
|
|
4
|
+
const invalid = () => new TypeError('Runner input must match the bounded runner/task-client/v0 contract');
|
|
5
|
+
function checkedJobId(value) {
|
|
6
|
+
if (!opaqueId(value) || pathLike(value)
|
|
7
|
+
|| /^(?:https?|ftp|file|data|javascript|bearer|basic):|^(?:sk[-_]|pk[-_]|gh[pousr]_|github_pat_|xox[baprs]-|eyJ)/i.test(value)) {
|
|
8
|
+
throw invalid();
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
function closed(value, required, optional = []) {
|
|
13
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
14
|
+
&& required.every((key) => Object.hasOwn(value, key))
|
|
15
|
+
&& Object.keys(value).every((key) => required.includes(key) || optional.includes(key));
|
|
16
|
+
}
|
|
17
|
+
// Match the core's input bounds and copy once so a caller cannot mutate a validated request
|
|
18
|
+
// while the asynchronous credential provider runs. Identity is never an input property.
|
|
19
|
+
function copyBoundedInput(value) {
|
|
20
|
+
let nodes = 0;
|
|
21
|
+
let chars = 0;
|
|
22
|
+
const ancestors = new Set();
|
|
23
|
+
const countText = (text) => {
|
|
24
|
+
chars += text.length;
|
|
25
|
+
if (text.length > 32768 || chars > 65536)
|
|
26
|
+
throw invalid();
|
|
27
|
+
return text;
|
|
28
|
+
};
|
|
29
|
+
const walk = (v, depth) => {
|
|
30
|
+
if (++nodes > 256)
|
|
31
|
+
throw invalid();
|
|
32
|
+
if (v === null || typeof v === 'boolean')
|
|
33
|
+
return v;
|
|
34
|
+
if (typeof v === 'string')
|
|
35
|
+
return countText(v);
|
|
36
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
37
|
+
return v;
|
|
38
|
+
if (typeof v !== 'object' || depth >= 6 || ancestors.has(v))
|
|
39
|
+
throw invalid();
|
|
40
|
+
ancestors.add(v);
|
|
41
|
+
try {
|
|
42
|
+
if (Array.isArray(v)) {
|
|
43
|
+
if (Object.getPrototypeOf(v) !== Array.prototype || v.length > 64 || Reflect.ownKeys(v).length !== v.length + 1)
|
|
44
|
+
throw invalid();
|
|
45
|
+
return Array.from({ length: v.length }, (_, index) => {
|
|
46
|
+
const d = Object.getOwnPropertyDescriptor(v, String(index));
|
|
47
|
+
if (!d || !('value' in d) || !d.enumerable)
|
|
48
|
+
throw invalid();
|
|
49
|
+
return walk(d.value, depth + 1);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const prototype = Object.getPrototypeOf(v);
|
|
53
|
+
if (prototype !== null && prototype !== Object.prototype)
|
|
54
|
+
throw invalid();
|
|
55
|
+
const keys = Reflect.ownKeys(v);
|
|
56
|
+
if (keys.length > 32)
|
|
57
|
+
throw invalid();
|
|
58
|
+
const out = Object.create(null);
|
|
59
|
+
for (const key of keys) {
|
|
60
|
+
if (typeof key !== 'string')
|
|
61
|
+
throw invalid();
|
|
62
|
+
countText(key);
|
|
63
|
+
const d = Object.getOwnPropertyDescriptor(v, key);
|
|
64
|
+
if (!('value' in d) || !d.enumerable)
|
|
65
|
+
throw invalid();
|
|
66
|
+
out[key] = walk(d.value, depth + 1);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
ancestors.delete(v);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return walk(value, 0);
|
|
75
|
+
}
|
|
76
|
+
function checkedStartInput(input) {
|
|
77
|
+
const v = copyBoundedInput(input);
|
|
78
|
+
if (!closed(v, ['task', 'workspaceRef', 'executionRef', 'limits', 'idempotencyKey'])
|
|
79
|
+
|| !closed(v.task, ['id', 'text'], ['meta']) || !opaqueId(v.task.id)
|
|
80
|
+
|| typeof v.task.text !== 'string' || !v.task.text.trim()
|
|
81
|
+
|| (Object.hasOwn(v.task, 'meta') && (v.task.meta === null || typeof v.task.meta !== 'object' || Array.isArray(v.task.meta)))
|
|
82
|
+
|| !opaqueId(v.workspaceRef) || pathLike(v.workspaceRef)
|
|
83
|
+
|| !closed(v.executionRef, ['kind', 'routeId'])
|
|
84
|
+
|| !['external-harness', 'internal-model'].includes(v.executionRef.kind) || !opaqueId(v.executionRef.routeId)
|
|
85
|
+
|| !closed(v.limits, ['maxDurationMs', 'maxOutputBytes'], ['maxEvents']) || !opaqueId(v.idempotencyKey))
|
|
86
|
+
throw invalid();
|
|
87
|
+
const limit = (n, maximum) => Number.isInteger(n) && n > 0 && n <= maximum;
|
|
88
|
+
if (!limit(v.limits.maxDurationMs, 86400000) || !limit(v.limits.maxOutputBytes, 67108864)
|
|
89
|
+
|| (Object.hasOwn(v.limits, 'maxEvents') && !limit(v.limits.maxEvents, 1000)))
|
|
90
|
+
throw invalid();
|
|
91
|
+
if (new TextEncoder().encode(JSON.stringify(v)).byteLength > 65536)
|
|
92
|
+
throw invalid();
|
|
93
|
+
return v;
|
|
94
|
+
}
|
|
95
|
+
/** Runner routes use the Genesis client's credential; the backend owns org/subject scoping. */
|
|
96
|
+
export function runnerModule(client) {
|
|
97
|
+
return Object.freeze({
|
|
98
|
+
catalog: (opts = {}) => client.request('runner_getCatalog', undefined, requestOptions(opts)),
|
|
99
|
+
jobs: Object.freeze({
|
|
100
|
+
list: (opts = {}) => client.request('runner_listJobs', undefined, requestOptions(opts)),
|
|
101
|
+
start: (input, opts = {}) => client.request('runner_startJob', { body: checkedStartInput(input) }, requestOptions(opts)),
|
|
102
|
+
get: (jobId, opts = {}) => client.request('runner_getJob', { jobId: checkedJobId(jobId) }, requestOptions(opts)),
|
|
103
|
+
events: (jobId, afterSeq = 0, opts = {}) => {
|
|
104
|
+
if (!Number.isSafeInteger(afterSeq) || afterSeq < 0)
|
|
105
|
+
throw invalid();
|
|
106
|
+
return client.request('runner_getJobEvents', { jobId: checkedJobId(jobId), afterSeq }, requestOptions(opts));
|
|
107
|
+
},
|
|
108
|
+
result: (jobId, opts = {}) => client.request('runner_getJobResult', { jobId: checkedJobId(jobId) }, requestOptions(opts)),
|
|
109
|
+
cancel: (jobId, opts = {}) => client.request('runner_cancelJob', { jobId: checkedJobId(jobId) }, requestOptions(opts)),
|
|
110
|
+
}),
|
|
111
|
+
});
|
|
112
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { operations } from './generated/schema.js';
|
|
2
|
+
export interface ServiceMeta {
|
|
3
|
+
name: string;
|
|
4
|
+
title: string;
|
|
5
|
+
upstream: string;
|
|
6
|
+
status: string;
|
|
7
|
+
statusNote?: string;
|
|
8
|
+
operations: number;
|
|
9
|
+
}
|
|
10
|
+
export interface OperationMeta {
|
|
11
|
+
method: string;
|
|
12
|
+
path: string;
|
|
13
|
+
service: string;
|
|
14
|
+
summary: string;
|
|
15
|
+
upstream: {
|
|
16
|
+
base: string;
|
|
17
|
+
method: string;
|
|
18
|
+
path: string;
|
|
19
|
+
status: string;
|
|
20
|
+
};
|
|
21
|
+
mcp: boolean;
|
|
22
|
+
internal: boolean;
|
|
23
|
+
public: boolean;
|
|
24
|
+
pathParams: readonly string[];
|
|
25
|
+
queryParams: readonly string[];
|
|
26
|
+
hasBody: boolean;
|
|
27
|
+
requestContentType?: string;
|
|
28
|
+
rawResponse?: boolean;
|
|
29
|
+
inputSchema: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
type Ops = operations;
|
|
32
|
+
type Clean<T> = [T] extends [never] ? {} : [NonNullable<T>] extends [never] ? {} : NonNullable<T>;
|
|
33
|
+
type Part<K extends keyof Ops, L extends 'path' | 'query'> = Ops[K] extends {
|
|
34
|
+
parameters: infer P;
|
|
35
|
+
} ? (P extends {
|
|
36
|
+
[X in L]?: infer T;
|
|
37
|
+
} ? Clean<T> : {}) : {};
|
|
38
|
+
type Body<K extends keyof Ops> = Ops[K] extends {
|
|
39
|
+
requestBody?: infer B;
|
|
40
|
+
} ? [NonNullable<B>] extends [never] ? {} : NonNullable<B> extends {
|
|
41
|
+
content: {
|
|
42
|
+
'application/json': infer J;
|
|
43
|
+
};
|
|
44
|
+
} ? (undefined extends B ? {
|
|
45
|
+
body?: J;
|
|
46
|
+
} : {
|
|
47
|
+
body: J;
|
|
48
|
+
}) : NonNullable<B> extends {
|
|
49
|
+
content: {
|
|
50
|
+
'multipart/form-data': unknown;
|
|
51
|
+
};
|
|
52
|
+
} ? (undefined extends B ? {
|
|
53
|
+
body?: FormData;
|
|
54
|
+
} : {
|
|
55
|
+
body: FormData;
|
|
56
|
+
}) : {} : {};
|
|
57
|
+
/** Flat input for an operation: path params + query params + `body`. */
|
|
58
|
+
export type OperationInput<K extends keyof Ops> = Part<K, 'path'> & Part<K, 'query'> & Body<K>;
|
|
59
|
+
type Ok<R> = R extends {
|
|
60
|
+
200: infer X;
|
|
61
|
+
} ? X : R extends {
|
|
62
|
+
201: infer X;
|
|
63
|
+
} ? X : R extends {
|
|
64
|
+
202: infer X;
|
|
65
|
+
} ? X : R extends {
|
|
66
|
+
204: unknown;
|
|
67
|
+
} ? {
|
|
68
|
+
content: {
|
|
69
|
+
'application/json': void;
|
|
70
|
+
};
|
|
71
|
+
} : unknown;
|
|
72
|
+
/** Parsed JSON success body for an operation. */
|
|
73
|
+
export type OperationOutput<K extends keyof Ops> = K extends 'hives_invoke_function' | 'hives_invoke_function_async' | 'hives_invoke_deployment' ? Response : Ops[K] extends {
|
|
74
|
+
responses: infer R;
|
|
75
|
+
} ? (Ok<R> extends {
|
|
76
|
+
content: {
|
|
77
|
+
'application/json': infer J;
|
|
78
|
+
};
|
|
79
|
+
} ? J : unknown) : unknown;
|
|
80
|
+
export {};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifesi/genesis",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "One typed SDK for every Genesis service (Foundry, Hives, Relays, IAM...) via the Genesis API gateway",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./spec.json": "./dist/genesis.openapi.json",
|
|
14
|
+
"./hives-node": {
|
|
15
|
+
"types": "./dist/hives-node.d.ts",
|
|
16
|
+
"default": "./dist/hives-node.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"undici": "6.29.0"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"gen": "node scripts/gen.mjs",
|
|
27
|
+
"build": "tsc -p tsconfig.json && cp ../../openapi/genesis.openapi.json dist/"
|
|
28
|
+
}
|
|
6
29
|
}
|
package/README.md
DELETED