@onesi/genesis-cli 0.0.0-stage → 0.1.13
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 +36 -2
- package/bin/genesis.js +3 -0
- package/dist/auth.d.ts +30 -0
- package/dist/auth.js +273 -0
- package/dist/beacons.d.ts +3 -0
- package/dist/beacons.js +94 -0
- package/dist/device-login.d.ts +25 -0
- package/dist/device-login.js +173 -0
- package/dist/dials.d.ts +7 -0
- package/dist/dials.js +96 -0
- package/dist/fleets.d.ts +4 -0
- package/dist/fleets.js +72 -0
- package/dist/flocks.d.ts +3 -0
- package/dist/flocks.js +72 -0
- package/dist/function-input.d.ts +3 -0
- package/dist/function-input.js +49 -0
- package/dist/henry.d.ts +3 -0
- package/dist/henry.js +26 -0
- package/dist/hives-marketplace.d.ts +10 -0
- package/dist/hives-marketplace.js +29 -0
- package/dist/hives-node-transport.d.ts +6 -0
- package/dist/hives-node-transport.js +147 -0
- package/dist/hives-operations.d.ts +9 -0
- package/dist/hives-operations.js +61 -0
- package/dist/hives-resources.d.ts +9 -0
- package/dist/hives-resources.js +94 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +640 -0
- package/dist/lifeid-native.d.ts +24 -0
- package/dist/lifeid-native.js +113 -0
- package/dist/minds-owner.d.ts +3 -0
- package/dist/minds-owner.js +42 -0
- package/dist/minds.d.ts +3 -0
- package/dist/minds.js +90 -0
- package/dist/output.d.ts +28 -0
- package/dist/output.js +46 -0
- package/dist/products.d.ts +14 -0
- package/dist/products.js +85 -0
- package/dist/relays-enrollment.d.ts +3 -0
- package/dist/relays-enrollment.js +7 -0
- package/dist/runner.d.ts +4 -0
- package/dist/runner.js +55 -0
- package/dist/secret-input.d.ts +14 -0
- package/dist/secret-input.js +85 -0
- package/dist/store.d.ts +39 -0
- package/dist/store.js +33 -0
- package/dist/wasm-input.d.ts +2 -0
- package/dist/wasm-input.js +31 -0
- package/package.json +51 -3
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { open } from 'node:fs/promises';
|
|
2
|
+
/** Read plaintext only from an explicitly selected file or stdin, never argv. */
|
|
3
|
+
export async function readSecretInput(options, limit) {
|
|
4
|
+
if (Boolean(options.file) === Boolean(options.stdin))
|
|
5
|
+
throw new Error('Choose exactly one input source: a file or --stdin. Secret values are not accepted as command arguments.');
|
|
6
|
+
const chunks = [];
|
|
7
|
+
let size = 0;
|
|
8
|
+
const append = (chunk) => {
|
|
9
|
+
size += chunk.byteLength;
|
|
10
|
+
if (size > limit)
|
|
11
|
+
throw new Error(`Secret input exceeds ${limit} UTF-8 bytes. Use a smaller value or batch.`);
|
|
12
|
+
chunks.push(chunk);
|
|
13
|
+
};
|
|
14
|
+
if (options.file) {
|
|
15
|
+
let file;
|
|
16
|
+
try {
|
|
17
|
+
file = await open(options.file, 'r');
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new Error('Could not open the secret input file. Check its path and permissions.');
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
for (;;) {
|
|
24
|
+
const buffer = new Uint8Array(Math.min(8192, limit + 1));
|
|
25
|
+
const { bytesRead } = await file.read(buffer, 0, buffer.length, null);
|
|
26
|
+
if (!bytesRead)
|
|
27
|
+
break;
|
|
28
|
+
append(buffer.subarray(0, bytesRead));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
await file.close();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
for await (const chunk of process.stdin)
|
|
37
|
+
append(typeof chunk === 'string' ? new TextEncoder().encode(chunk) : chunk);
|
|
38
|
+
}
|
|
39
|
+
const bytes = new Uint8Array(size);
|
|
40
|
+
let offset = 0;
|
|
41
|
+
for (const chunk of chunks) {
|
|
42
|
+
bytes.set(chunk, offset);
|
|
43
|
+
offset += chunk.byteLength;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
throw new Error('Secret input must be valid UTF-8 text.');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function validateSecretValue(value) {
|
|
53
|
+
if (!value.length || new TextEncoder().encode(value).length > 65536)
|
|
54
|
+
throw new Error('Secret values must contain 1–65,536 UTF-8 bytes.');
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
export function validateSecret(input) {
|
|
58
|
+
if (!input || typeof input !== 'object')
|
|
59
|
+
throw new Error('Each secret needs a name and value.');
|
|
60
|
+
const { name, value, description } = input;
|
|
61
|
+
if (typeof name !== 'string' || name.length > 255 || !/^[A-Za-z][A-Za-z0-9_]*$/.test(name))
|
|
62
|
+
throw new Error('Secret names must start with a letter and contain only letters, numbers and underscores (up to 255 characters).');
|
|
63
|
+
if (typeof value !== 'string')
|
|
64
|
+
throw new Error('Each secret value must be a string.');
|
|
65
|
+
if (description !== undefined && description !== null && (typeof description !== 'string' || description.length > 500))
|
|
66
|
+
throw new Error('Secret descriptions must contain at most 500 characters.');
|
|
67
|
+
return { name, value: validateSecretValue(value), ...(typeof description === 'string' ? { description } : {}) };
|
|
68
|
+
}
|
|
69
|
+
export function parseSecretBatch(text) {
|
|
70
|
+
let data;
|
|
71
|
+
try {
|
|
72
|
+
data = JSON.parse(text);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
throw new Error('Bulk input must be a JSON array with secret name and value fields.');
|
|
76
|
+
}
|
|
77
|
+
if (!Array.isArray(data) || !data.length)
|
|
78
|
+
throw new Error('Bulk input must be a non-empty JSON array.');
|
|
79
|
+
const batch = data.map(validateSecret);
|
|
80
|
+
if (new Set(batch.map((secret) => secret.name)).size !== batch.length)
|
|
81
|
+
throw new Error('Each secret name must appear once in a bulk update.');
|
|
82
|
+
if (new TextEncoder().encode(JSON.stringify(batch)).length > 256 * 1024)
|
|
83
|
+
throw new Error('Bulk input must fit within 256 KiB. Split it into smaller batches.');
|
|
84
|
+
return batch;
|
|
85
|
+
}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Saved `genesis login`: kept in the OS keychain (macOS Keychain, Windows Credential Manager, libsecret). */
|
|
2
|
+
export interface SavedLogin {
|
|
3
|
+
access_token: string;
|
|
4
|
+
refresh_token?: string;
|
|
5
|
+
user?: {
|
|
6
|
+
id: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
first_name?: string | null;
|
|
9
|
+
last_name?: string | null;
|
|
10
|
+
};
|
|
11
|
+
organization_id?: string;
|
|
12
|
+
/** epoch seconds, from the access token's exp claim */
|
|
13
|
+
expires_at?: number;
|
|
14
|
+
client_id: string;
|
|
15
|
+
/** One account provenance: the native bridge, or the RFC 8628 device grant. Legacy raw AuthKit credentials are never reused. */
|
|
16
|
+
auth?: {
|
|
17
|
+
kind: 'lifeid-bridge';
|
|
18
|
+
issuer: string;
|
|
19
|
+
audience: string;
|
|
20
|
+
product_id: string;
|
|
21
|
+
redirect_uri: string;
|
|
22
|
+
principal_id: string;
|
|
23
|
+
session_id: string;
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'lifeid-device';
|
|
26
|
+
issuer: string;
|
|
27
|
+
client_id: string;
|
|
28
|
+
principal_id: string;
|
|
29
|
+
session_id: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface CredentialStore {
|
|
33
|
+
get(): Promise<SavedLogin | undefined>;
|
|
34
|
+
set(v: SavedLogin): Promise<void>;
|
|
35
|
+
clear(): Promise<boolean>;
|
|
36
|
+
readonly kind: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function keychainStore(): Promise<CredentialStore>;
|
|
39
|
+
export declare function memoryStore(initial?: SavedLogin): CredentialStore;
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const SERVICE = 'one.life.genesis';
|
|
2
|
+
const ACCOUNT = 'default';
|
|
3
|
+
export async function keychainStore() {
|
|
4
|
+
let Entry;
|
|
5
|
+
try {
|
|
6
|
+
({ Entry } = await import('@napi-rs/keyring'));
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
throw new Error('OS keychain is unavailable (@napi-rs/keyring not installed). Use GENESIS_API_KEY instead.');
|
|
10
|
+
}
|
|
11
|
+
const entry = new Entry(SERVICE, ACCOUNT);
|
|
12
|
+
return {
|
|
13
|
+
kind: 'os-keychain',
|
|
14
|
+
async get() { try {
|
|
15
|
+
const s = entry.getPassword();
|
|
16
|
+
return s ? JSON.parse(s) : undefined;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
} },
|
|
21
|
+
async set(v) { entry.setPassword(JSON.stringify(v)); },
|
|
22
|
+
async clear() { try {
|
|
23
|
+
return entry.deletePassword();
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
} },
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function memoryStore(initial) {
|
|
31
|
+
let v = initial;
|
|
32
|
+
return { kind: 'memory', async get() { return v; }, async set(x) { v = x; }, async clear() { const had = !!v; v = undefined; return had; } };
|
|
33
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { open } from 'node:fs/promises';
|
|
2
|
+
import { MAX_WASM_BYTES } from '@onesi/genesis';
|
|
3
|
+
/** Read only the explicitly requested regular file, with a bounded allocation. */
|
|
4
|
+
export async function readWasmFile(path) {
|
|
5
|
+
let file;
|
|
6
|
+
try {
|
|
7
|
+
file = await open(path, 'r');
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
throw new Error('Could not open the WASM file. Check its path and permissions.');
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const stat = await file.stat();
|
|
14
|
+
if (!stat.isFile() || stat.size < 4 || stat.size > MAX_WASM_BYTES)
|
|
15
|
+
throw new Error('Choose a regular WASM file of 4 bytes to 10 MiB.');
|
|
16
|
+
const bytes = new Uint8Array(MAX_WASM_BYTES + 1);
|
|
17
|
+
let size = 0;
|
|
18
|
+
for (;;) {
|
|
19
|
+
const { bytesRead } = await file.read(bytes, size, bytes.length - size, null);
|
|
20
|
+
if (!bytesRead)
|
|
21
|
+
break;
|
|
22
|
+
size += bytesRead;
|
|
23
|
+
if (size > MAX_WASM_BYTES)
|
|
24
|
+
throw new Error('WASM file exceeds 10 MiB.');
|
|
25
|
+
}
|
|
26
|
+
return new Blob([bytes.slice(0, size)], { type: 'application/wasm' });
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await file.close();
|
|
30
|
+
}
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onesi/genesis-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
|
|
3
|
+
"version": "0.1.13",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/l1felabs/genesis-api.git",
|
|
7
|
+
"directory": "packages/cli"
|
|
8
|
+
},
|
|
9
|
+
"description": "genesis: one CLI for every Genesis service",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"bin": {
|
|
12
|
+
"genesis": "bin/genesis.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"genesis",
|
|
16
|
+
"oneos",
|
|
17
|
+
"sdk",
|
|
18
|
+
"cli",
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"ai-agents",
|
|
22
|
+
"api"
|
|
23
|
+
],
|
|
24
|
+
"author": "One Superintelligence, Inc.",
|
|
25
|
+
"homepage": "https://os.one.ml/docs",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20.19"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin",
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"commander": "^14.0.0",
|
|
35
|
+
"undici": "6.29.0",
|
|
36
|
+
"@onesi/genesis": "0.1.13"
|
|
37
|
+
},
|
|
38
|
+
"optionalDependencies": {
|
|
39
|
+
"@napi-rs/keyring": "^1.2.0"
|
|
40
|
+
},
|
|
41
|
+
"exports": {
|
|
42
|
+
"./auth": {
|
|
43
|
+
"types": "./dist/auth.d.ts",
|
|
44
|
+
"default": "./dist/auth.js"
|
|
45
|
+
},
|
|
46
|
+
"./store": {
|
|
47
|
+
"types": "./dist/store.d.ts",
|
|
48
|
+
"default": "./dist/store.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.json"
|
|
53
|
+
}
|
|
6
54
|
}
|