@nimbus-dev/sdk 1.1.2
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 +34 -0
- package/dist/audit-logger.d.ts +6 -0
- package/dist/audit-logger.d.ts.map +1 -0
- package/dist/audit-logger.js +18 -0
- package/dist/audit-logger.js.map +1 -0
- package/dist/contract-tests.d.ts +45 -0
- package/dist/contract-tests.d.ts.map +1 -0
- package/dist/contract-tests.js +191 -0
- package/dist/contract-tests.js.map +1 -0
- package/dist/crypto/app-store-connect-jwt.d.ts +19 -0
- package/dist/crypto/app-store-connect-jwt.d.ts.map +1 -0
- package/dist/crypto/app-store-connect-jwt.js +30 -0
- package/dist/crypto/app-store-connect-jwt.js.map +1 -0
- package/dist/crypto/canonical-json.d.ts +36 -0
- package/dist/crypto/canonical-json.d.ts.map +1 -0
- package/dist/crypto/canonical-json.js +75 -0
- package/dist/crypto/canonical-json.js.map +1 -0
- package/dist/crypto/jwt.d.ts +30 -0
- package/dist/crypto/jwt.d.ts.map +1 -0
- package/dist/crypto/jwt.js +30 -0
- package/dist/crypto/jwt.js.map +1 -0
- package/dist/crypto/service-account-token.d.ts +36 -0
- package/dist/crypto/service-account-token.d.ts.map +1 -0
- package/dist/crypto/service-account-token.js +96 -0
- package/dist/crypto/service-account-token.js.map +1 -0
- package/dist/crypto/verify-signature.d.ts +57 -0
- package/dist/crypto/verify-signature.d.ts.map +1 -0
- package/dist/crypto/verify-signature.js +102 -0
- package/dist/crypto/verify-signature.js.map +1 -0
- package/dist/distribution-channel.d.ts +34 -0
- package/dist/distribution-channel.d.ts.map +1 -0
- package/dist/distribution-channel.js +73 -0
- package/dist/distribution-channel.js.map +1 -0
- package/dist/hitl-request.d.ts +7 -0
- package/dist/hitl-request.d.ts.map +1 -0
- package/dist/hitl-request.js +15 -0
- package/dist/hitl-request.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/index.d.ts +2 -0
- package/dist/ipc/index.d.ts.map +1 -0
- package/dist/ipc/index.js +2 -0
- package/dist/ipc/index.js.map +1 -0
- package/dist/ipc/ndjson-line-reader.d.ts +20 -0
- package/dist/ipc/ndjson-line-reader.d.ts.map +1 -0
- package/dist/ipc/ndjson-line-reader.js +56 -0
- package/dist/ipc/ndjson-line-reader.js.map +1 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +23 -0
- package/dist/server.js.map +1 -0
- package/dist/testing/index.d.ts +15 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +17 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/sandbox-contract.d.ts +83 -0
- package/dist/testing/sandbox-contract.d.ts.map +1 -0
- package/dist/testing/sandbox-contract.js +105 -0
- package/dist/testing/sandbox-contract.js.map +1 -0
- package/dist/testing/sandbox-probe.d.ts +23 -0
- package/dist/testing/sandbox-probe.d.ts.map +1 -0
- package/dist/testing/sandbox-probe.js +78 -0
- package/dist/testing/sandbox-probe.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
- package/src/audit-logger.test.ts +33 -0
- package/src/audit-logger.ts +23 -0
- package/src/contract-tests.test.ts +203 -0
- package/src/contract-tests.ts +220 -0
- package/src/crypto/app-store-connect-jwt.test.ts +80 -0
- package/src/crypto/app-store-connect-jwt.ts +42 -0
- package/src/crypto/canonical-json.test.ts +121 -0
- package/src/crypto/canonical-json.ts +73 -0
- package/src/crypto/jwt.test.ts +62 -0
- package/src/crypto/jwt.ts +45 -0
- package/src/crypto/service-account-token.test.ts +128 -0
- package/src/crypto/service-account-token.ts +116 -0
- package/src/crypto/verify-signature.test.ts +118 -0
- package/src/crypto/verify-signature.ts +138 -0
- package/src/distribution-channel.test.ts +107 -0
- package/src/distribution-channel.ts +105 -0
- package/src/hitl-request.ts +22 -0
- package/src/index.ts +59 -0
- package/src/ipc/index.ts +5 -0
- package/src/ipc/ndjson-line-reader.test.ts +64 -0
- package/src/ipc/ndjson-line-reader.ts +70 -0
- package/src/plugin-api-v1.test.ts +50 -0
- package/src/sdk.test.ts +23 -0
- package/src/server.test.ts +96 -0
- package/src/server.ts +39 -0
- package/src/testing/index.ts +18 -0
- package/src/testing/sandbox-contract.test.ts +146 -0
- package/src/testing/sandbox-contract.ts +155 -0
- package/src/testing/sandbox-probe.ts +87 -0
- package/src/types.ts +42 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google service-account OAuth2 access tokens via the JWT-bearer grant.
|
|
3
|
+
*
|
|
4
|
+
* Google Cloud REST APIs (App Distribution, BigQuery, …) accept a short-lived
|
|
5
|
+
* OAuth2 access token. This mints one from a service-account key (the JSON the
|
|
6
|
+
* developer downloads) by signing an RS256 JWT assertion and exchanging it at
|
|
7
|
+
* the token endpoint — no `googleapis` dependency. Shared so the gateway sync
|
|
8
|
+
* and a connector's MCP server sign identically without duplicating the flow.
|
|
9
|
+
*
|
|
10
|
+
* See: https://developers.google.com/identity/protocols/oauth2/service-account
|
|
11
|
+
*/
|
|
12
|
+
import { signJwt } from "./jwt";
|
|
13
|
+
const SCOPE_CLOUD_PLATFORM = "https://www.googleapis.com/auth/cloud-platform";
|
|
14
|
+
const DEFAULT_TOKEN_URI = "https://oauth2.googleapis.com/token";
|
|
15
|
+
/** Google caps SA assertion lifetime at 1 hour. */
|
|
16
|
+
const ASSERTION_TTL_SECONDS = 3600;
|
|
17
|
+
const JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer";
|
|
18
|
+
function asString(value) {
|
|
19
|
+
return typeof value === "string" && value !== "" ? value : undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a service-account key JSON string into the fields the JWT-bearer flow
|
|
23
|
+
* needs. Returns null on malformed JSON or a missing `client_email` /
|
|
24
|
+
* `private_key`; `token_uri` defaults to Google's endpoint when absent.
|
|
25
|
+
*/
|
|
26
|
+
export function parseServiceAccountJson(json) {
|
|
27
|
+
let parsed;
|
|
28
|
+
try {
|
|
29
|
+
parsed = JSON.parse(json);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const obj = parsed;
|
|
38
|
+
const clientEmail = asString(obj["client_email"]);
|
|
39
|
+
const privateKey = asString(obj["private_key"]);
|
|
40
|
+
if (clientEmail === undefined || privateKey === undefined) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
clientEmail,
|
|
45
|
+
privateKey,
|
|
46
|
+
tokenUri: asString(obj["token_uri"]) ?? DEFAULT_TOKEN_URI,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Sign an RS256 JWT assertion for the JWT-bearer grant. `nowMs` is injectable
|
|
51
|
+
* so tests can assert deterministic `iat`/`exp`; `scope` defaults to
|
|
52
|
+
* `cloud-platform`.
|
|
53
|
+
*/
|
|
54
|
+
export function signServiceAccountAssertion(sa, nowMs = Date.now(), scope = SCOPE_CLOUD_PLATFORM) {
|
|
55
|
+
const nowSec = Math.floor(nowMs / 1000);
|
|
56
|
+
return signJwt({
|
|
57
|
+
header: { alg: "RS256", typ: "JWT" },
|
|
58
|
+
payload: {
|
|
59
|
+
iss: sa.clientEmail,
|
|
60
|
+
scope,
|
|
61
|
+
aud: sa.tokenUri,
|
|
62
|
+
iat: nowSec,
|
|
63
|
+
exp: nowSec + ASSERTION_TTL_SECONDS,
|
|
64
|
+
},
|
|
65
|
+
privateKeyPem: sa.privateKey,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Exchange a service-account assertion for an OAuth2 access token. `fetchFn` and
|
|
70
|
+
* `nowMs` are injectable for tests; the live path uses the global `fetch`.
|
|
71
|
+
* Returns null when the token endpoint declines the assertion.
|
|
72
|
+
*/
|
|
73
|
+
export async function mintGoogleAccessToken(sa, fetchFn = globalThis.fetch, nowMs = Date.now(), scope = SCOPE_CLOUD_PLATFORM) {
|
|
74
|
+
const assertion = signServiceAccountAssertion(sa, nowMs, scope);
|
|
75
|
+
const body = new URLSearchParams({ grant_type: JWT_BEARER_GRANT, assertion }).toString();
|
|
76
|
+
const res = await fetchFn(sa.tokenUri, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
79
|
+
body,
|
|
80
|
+
});
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
parsed = (await res.json());
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
return asString(parsed["access_token"]) ?? null;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=service-account-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-account-token.js","sourceRoot":"","sources":["../../src/crypto/service-account-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ed25519 sign + verify primitives for extension manifest signatures.
|
|
3
|
+
* Connector authors use this to sign manifests; the gateway uses it to verify
|
|
4
|
+
* at install + every startup (I16 wiring sites).
|
|
5
|
+
*/
|
|
6
|
+
export declare class PublisherKeyMismatch extends Error {
|
|
7
|
+
readonly name = "PublisherKeyMismatch";
|
|
8
|
+
}
|
|
9
|
+
export declare class SignatureInvalidFormat extends Error {
|
|
10
|
+
readonly name = "SignatureInvalidFormat";
|
|
11
|
+
}
|
|
12
|
+
export declare class SignatureInvalid extends Error {
|
|
13
|
+
readonly name = "SignatureInvalid";
|
|
14
|
+
}
|
|
15
|
+
export type SignatureDisableReason = "publisher_key_missing" | "publisher_key_mismatch" | "signature_failed" | "signature_malformed";
|
|
16
|
+
export declare function encodeBase64(bytes: Uint8Array): string;
|
|
17
|
+
export declare function decodeBase64(s: string): Uint8Array;
|
|
18
|
+
type SignedManifestShape = {
|
|
19
|
+
publisher?: {
|
|
20
|
+
id: string;
|
|
21
|
+
key: string;
|
|
22
|
+
};
|
|
23
|
+
signature?: string;
|
|
24
|
+
[k: string]: unknown;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Verify `manifest.signature` against the canonical bytes of the manifest
|
|
28
|
+
* (with `signature` stripped), the declared `manifest.publisher.key`, and
|
|
29
|
+
* the externally-resolved `resolvedPubkey`. Throws on any mismatch.
|
|
30
|
+
*
|
|
31
|
+
* Caller must check `manifest.publisher !== undefined` first — this function
|
|
32
|
+
* does not gate the unsigned case.
|
|
33
|
+
*/
|
|
34
|
+
export declare function verifyManifestSignature(manifest: SignedManifestShape, resolvedPubkey: Uint8Array): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Deterministically sign a manifest's canonical bytes with `privkey` (32-byte
|
|
37
|
+
* Ed25519 seed). Returns the 64-byte signature as base64. Any existing
|
|
38
|
+
* `signature` field on the manifest is ignored (stripped by
|
|
39
|
+
* `canonicalizeManifest`).
|
|
40
|
+
*/
|
|
41
|
+
export declare function signManifest(manifest: SignedManifestShape, privkey: Uint8Array): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Generate a fresh Ed25519 keypair via WebCrypto and export both halves as
|
|
44
|
+
* raw 32-byte arrays. Used by `nimbus extension keygen` and by every test
|
|
45
|
+
* fixture (no committed crypto material — see spec §6.3).
|
|
46
|
+
*/
|
|
47
|
+
export declare function generateEd25519Keypair(): {
|
|
48
|
+
privkey: Uint8Array;
|
|
49
|
+
pubkey: Uint8Array;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Map a verification error class to the `SignatureDisableReason` string the
|
|
53
|
+
* `SignatureDisabledRegistry` (hard-disable.ts) records.
|
|
54
|
+
*/
|
|
55
|
+
export declare function errorToHardDisableReason(err: unknown): SignatureDisableReason;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=verify-signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-signature.d.ts","sourceRoot":"","sources":["../../src/crypto/verify-signature.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAkB,IAAI,0BAA0B;CACjD;AACD,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,SAAkB,IAAI,4BAA4B;CACnD;AACD,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,SAAkB,IAAI,sBAAsB;CAC7C;AAED,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,wBAAwB,GACxB,kBAAkB,GAClB,qBAAqB,CAAC;AAE1B,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEtD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAElD;AAWD,KAAK,mBAAmB,GAAG;IACzB,SAAS,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,mBAAmB,EAC7B,cAAc,EAAE,UAAU,GACzB,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,MAAM,CAAC,CAajB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAQpF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,CAK7E"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ed25519 sign + verify primitives for extension manifest signatures.
|
|
3
|
+
* Connector authors use this to sign manifests; the gateway uses it to verify
|
|
4
|
+
* at install + every startup (I16 wiring sites).
|
|
5
|
+
*/
|
|
6
|
+
import { canonicalizeManifest } from "./canonical-json";
|
|
7
|
+
export class PublisherKeyMismatch extends Error {
|
|
8
|
+
name = "PublisherKeyMismatch";
|
|
9
|
+
}
|
|
10
|
+
export class SignatureInvalidFormat extends Error {
|
|
11
|
+
name = "SignatureInvalidFormat";
|
|
12
|
+
}
|
|
13
|
+
export class SignatureInvalid extends Error {
|
|
14
|
+
name = "SignatureInvalid";
|
|
15
|
+
}
|
|
16
|
+
export function encodeBase64(bytes) {
|
|
17
|
+
return Buffer.from(bytes).toString("base64");
|
|
18
|
+
}
|
|
19
|
+
export function decodeBase64(s) {
|
|
20
|
+
return new Uint8Array(Buffer.from(s, "base64"));
|
|
21
|
+
}
|
|
22
|
+
function constantTimeBytesEqual(a, b) {
|
|
23
|
+
if (a.length !== b.length)
|
|
24
|
+
return false;
|
|
25
|
+
let diff = 0;
|
|
26
|
+
for (let i = 0; i < a.length; i++) {
|
|
27
|
+
diff |= (a[i] ?? 0) ^ (b[i] ?? 0);
|
|
28
|
+
}
|
|
29
|
+
return diff === 0;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Verify `manifest.signature` against the canonical bytes of the manifest
|
|
33
|
+
* (with `signature` stripped), the declared `manifest.publisher.key`, and
|
|
34
|
+
* the externally-resolved `resolvedPubkey`. Throws on any mismatch.
|
|
35
|
+
*
|
|
36
|
+
* Caller must check `manifest.publisher !== undefined` first — this function
|
|
37
|
+
* does not gate the unsigned case.
|
|
38
|
+
*/
|
|
39
|
+
export async function verifyManifestSignature(manifest, resolvedPubkey) {
|
|
40
|
+
if (manifest.publisher === undefined || manifest.signature === undefined) {
|
|
41
|
+
throw new Error("verifyManifestSignature called on unsigned manifest — caller must check first");
|
|
42
|
+
}
|
|
43
|
+
if (resolvedPubkey.length !== 32)
|
|
44
|
+
throw new SignatureInvalidFormat();
|
|
45
|
+
const declaredPubkey = decodeBase64(manifest.publisher.key);
|
|
46
|
+
if (declaredPubkey.length !== 32)
|
|
47
|
+
throw new SignatureInvalidFormat();
|
|
48
|
+
if (!constantTimeBytesEqual(declaredPubkey, resolvedPubkey)) {
|
|
49
|
+
throw new PublisherKeyMismatch();
|
|
50
|
+
}
|
|
51
|
+
const sig = decodeBase64(manifest.signature);
|
|
52
|
+
if (sig.length !== 64)
|
|
53
|
+
throw new SignatureInvalidFormat();
|
|
54
|
+
const canonical = canonicalizeManifest(manifest);
|
|
55
|
+
const cryptoKey = await crypto.subtle.importKey("raw", new Uint8Array(resolvedPubkey), { name: "Ed25519" }, false, ["verify"]);
|
|
56
|
+
const ok = await crypto.subtle.verify("Ed25519", cryptoKey, new Uint8Array(sig), new Uint8Array(canonical));
|
|
57
|
+
if (!ok)
|
|
58
|
+
throw new SignatureInvalid();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Deterministically sign a manifest's canonical bytes with `privkey` (32-byte
|
|
62
|
+
* Ed25519 seed). Returns the 64-byte signature as base64. Any existing
|
|
63
|
+
* `signature` field on the manifest is ignored (stripped by
|
|
64
|
+
* `canonicalizeManifest`).
|
|
65
|
+
*/
|
|
66
|
+
export async function signManifest(manifest, privkey) {
|
|
67
|
+
if (privkey.length !== 32)
|
|
68
|
+
throw new SignatureInvalidFormat();
|
|
69
|
+
const d = Buffer.from(privkey).toString("base64url");
|
|
70
|
+
const cryptoKey = await crypto.subtle.importKey("jwk", { kty: "OKP", crv: "Ed25519", d }, { name: "Ed25519" }, false, ["sign"]);
|
|
71
|
+
const canonical = canonicalizeManifest(manifest);
|
|
72
|
+
const sig = await crypto.subtle.sign("Ed25519", cryptoKey, new Uint8Array(canonical));
|
|
73
|
+
return encodeBase64(new Uint8Array(sig));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate a fresh Ed25519 keypair via WebCrypto and export both halves as
|
|
77
|
+
* raw 32-byte arrays. Used by `nimbus extension keygen` and by every test
|
|
78
|
+
* fixture (no committed crypto material — see spec §6.3).
|
|
79
|
+
*/
|
|
80
|
+
export function generateEd25519Keypair() {
|
|
81
|
+
const nodeCrypto = require("node:crypto");
|
|
82
|
+
const { privateKey, publicKey } = nodeCrypto.generateKeyPairSync("ed25519");
|
|
83
|
+
const privJwk = privateKey.export({ format: "jwk" });
|
|
84
|
+
const pubJwk = publicKey.export({ format: "jwk" });
|
|
85
|
+
const privkey = new Uint8Array(Buffer.from(privJwk.d, "base64url"));
|
|
86
|
+
const pubkey = new Uint8Array(Buffer.from(pubJwk.x, "base64url"));
|
|
87
|
+
return { privkey, pubkey };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Map a verification error class to the `SignatureDisableReason` string the
|
|
91
|
+
* `SignatureDisabledRegistry` (hard-disable.ts) records.
|
|
92
|
+
*/
|
|
93
|
+
export function errorToHardDisableReason(err) {
|
|
94
|
+
if (err instanceof PublisherKeyMismatch)
|
|
95
|
+
return "publisher_key_mismatch";
|
|
96
|
+
if (err instanceof SignatureInvalidFormat)
|
|
97
|
+
return "signature_malformed";
|
|
98
|
+
if (err instanceof SignatureInvalid)
|
|
99
|
+
return "signature_failed";
|
|
100
|
+
return "signature_failed";
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=verify-signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-signature.js","sourceRoot":"","sources":["../../src/crypto/verify-signature.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channels a Nimbus binary can be distributed through. When Nimbus runs from a
|
|
3
|
+
* package-manager install, the self-updater steps aside so the package manager
|
|
4
|
+
* owns updates.
|
|
5
|
+
*
|
|
6
|
+
* Lives in the SDK so the gateway and CLI share one copy: the `cli` package
|
|
7
|
+
* reaches the gateway over IPC only (no source imports), so a shared pure helper
|
|
8
|
+
* must live in a package both may depend on — the same pattern the manifest
|
|
9
|
+
* signer uses.
|
|
10
|
+
*/
|
|
11
|
+
export type DistributionChannel = "homebrew" | "scoop" | "winget" | "apt" | "yum" | "msi" | "pkg";
|
|
12
|
+
export interface ResolveChannelOptions {
|
|
13
|
+
/** Defaults to `process.env`. */
|
|
14
|
+
env?: Record<string, string | undefined>;
|
|
15
|
+
/** Defaults to `process.execPath`. */
|
|
16
|
+
execPath?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves symlinks so a package manager's real install path (e.g. Homebrew's
|
|
19
|
+
* Cellar) is inspected rather than the `bin` symlink that launched the process.
|
|
20
|
+
* Injectable for tests; defaults to a safe `realpathSync` that falls back to the
|
|
21
|
+
* input path if resolution fails.
|
|
22
|
+
*/
|
|
23
|
+
realpath?: (p: string) => string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the distribution channel this binary was installed through, or `null`
|
|
27
|
+
* for a plain/direct-download install (where the self-updater stays enabled).
|
|
28
|
+
* An explicit `NIMBUS_DISTRIBUTION_CHANNEL` env marker takes precedence over
|
|
29
|
+
* path heuristics; an unknown marker value is ignored.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveDistributionChannel(opts?: ResolveChannelOptions): DistributionChannel | null;
|
|
32
|
+
/** Human-facing upgrade hint per channel, used by `nimbus update`. */
|
|
33
|
+
export declare function channelUpgradeHint(channel: DistributionChannel): string;
|
|
34
|
+
//# sourceMappingURL=distribution-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distribution-channel.d.ts","sourceRoot":"","sources":["../src/distribution-channel.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAYlG,MAAM,WAAW,qBAAqB;IACpC,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAClC;AAmCD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,GAAE,qBAA0B,GAC/B,mBAAmB,GAAG,IAAI,CAK5B;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAiBvE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
const KNOWN_CHANNELS = new Set([
|
|
3
|
+
"homebrew",
|
|
4
|
+
"scoop",
|
|
5
|
+
"winget",
|
|
6
|
+
"apt",
|
|
7
|
+
"yum",
|
|
8
|
+
"msi",
|
|
9
|
+
"pkg",
|
|
10
|
+
]);
|
|
11
|
+
function safeRealpath(p) {
|
|
12
|
+
try {
|
|
13
|
+
return realpathSync(p);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return p;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function fromEnv(env) {
|
|
20
|
+
const raw = env["NIMBUS_DISTRIBUTION_CHANNEL"];
|
|
21
|
+
if (raw && KNOWN_CHANNELS.has(raw)) {
|
|
22
|
+
return raw;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function fromPath(execPath, realpath) {
|
|
27
|
+
// Resolve symlinks first: package managers expose the binary via a symlink whose
|
|
28
|
+
// own path may not contain the tell-tale Cellar/apps segment.
|
|
29
|
+
const resolved = realpath(execPath);
|
|
30
|
+
const p = resolved.replaceAll("\\", "/").toLowerCase();
|
|
31
|
+
// Homebrew: macOS `/opt/homebrew/Cellar/...` or `/usr/local/Cellar/...`,
|
|
32
|
+
// Linuxbrew `/home/linuxbrew/.linuxbrew/...`.
|
|
33
|
+
if (p.includes("/cellar/") || p.includes("/.linuxbrew/")) {
|
|
34
|
+
return "homebrew";
|
|
35
|
+
}
|
|
36
|
+
// Scoop: `~/scoop/apps/<app>/...`.
|
|
37
|
+
if (p.includes("/scoop/apps/")) {
|
|
38
|
+
return "scoop";
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the distribution channel this binary was installed through, or `null`
|
|
44
|
+
* for a plain/direct-download install (where the self-updater stays enabled).
|
|
45
|
+
* An explicit `NIMBUS_DISTRIBUTION_CHANNEL` env marker takes precedence over
|
|
46
|
+
* path heuristics; an unknown marker value is ignored.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveDistributionChannel(opts = {}) {
|
|
49
|
+
const env = opts.env ?? process.env;
|
|
50
|
+
const execPath = opts.execPath ?? process.execPath;
|
|
51
|
+
const realpath = opts.realpath ?? safeRealpath;
|
|
52
|
+
return fromEnv(env) ?? fromPath(execPath, realpath);
|
|
53
|
+
}
|
|
54
|
+
/** Human-facing upgrade hint per channel, used by `nimbus update`. */
|
|
55
|
+
export function channelUpgradeHint(channel) {
|
|
56
|
+
switch (channel) {
|
|
57
|
+
case "homebrew":
|
|
58
|
+
return "Installed via Homebrew — run 'brew upgrade nimbus' to update.";
|
|
59
|
+
case "scoop":
|
|
60
|
+
return "Installed via Scoop — run 'scoop update nimbus' to update.";
|
|
61
|
+
case "winget":
|
|
62
|
+
return "Installed via winget — run 'winget upgrade NimbusAgent.Nimbus' to update.";
|
|
63
|
+
case "apt":
|
|
64
|
+
return "Installed via apt — run 'sudo apt update && sudo apt upgrade nimbus' to update.";
|
|
65
|
+
case "yum":
|
|
66
|
+
return "Installed via dnf/yum — run 'sudo dnf upgrade nimbus' to update.";
|
|
67
|
+
case "msi":
|
|
68
|
+
return "Installed via the Windows installer — download the latest .msi from the releases page.";
|
|
69
|
+
case "pkg":
|
|
70
|
+
return "Installed via the macOS installer — download the latest .pkg from the releases page.";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=distribution-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distribution-channel.js","sourceRoot":"","sources":["../src/distribution-channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAcvC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAsB;IAClD,UAAU;IACV,OAAO;IACP,QAAQ;IACR,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;CACmC,CAAC,CAAC;AAgB5C,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,GAAuC;IACtD,MAAM,GAAG,GAAG,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC/C,IAAI,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,GAA0B,CAAC,EAAE,CAAC;QAC1D,OAAO,GAA0B,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB,EAAE,QAA+B;IACjE,iFAAiF;IACjF,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,yEAAyE;IACzE,8CAA8C;IAC9C,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACzD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,mCAAmC;IACnC,IAAI,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAA8B,EAAE;IAEhC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,YAAY,CAAC;IAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC7D,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,+DAA+D,CAAC;QACzE,KAAK,OAAO;YACV,OAAO,4DAA4D,CAAC;QACtE,KAAK,QAAQ;YACX,OAAO,2EAA2E,CAAC;QACrF,KAAK,KAAK;YACR,OAAO,iFAAiF,CAAC;QAC3F,KAAK,KAAK;YACR,OAAO,kEAAkE,CAAC;QAC5E,KAAK,KAAK;YACR,OAAO,wFAAwF,CAAC;QAClG,KAAK,KAAK;YACR,OAAO,sFAAsF,CAAC;IAClG,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl-request.d.ts","sourceRoot":"","sources":["../src/hitl-request.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAelE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function isHitlRequest(value) {
|
|
2
|
+
if (typeof value !== "object" || value === null) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
const candidate = value;
|
|
6
|
+
const actionId = candidate["actionId"];
|
|
7
|
+
const summary = candidate["summary"];
|
|
8
|
+
const diff = candidate["diff"];
|
|
9
|
+
return (typeof actionId === "string" &&
|
|
10
|
+
actionId.length > 0 &&
|
|
11
|
+
typeof summary === "string" &&
|
|
12
|
+
summary.length > 0 &&
|
|
13
|
+
(diff === undefined || typeof diff === "string"));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=hitl-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl-request.js","sourceRoot":"","sources":["../src/hitl-request.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,SAAS,GAAG,KAAgC,CAAC;IACnD,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,CACL,OAAO,QAAQ,KAAK,QAAQ;QAC5B,QAAQ,CAAC,MAAM,GAAG,CAAC;QACnB,OAAO,OAAO,KAAK,QAAQ;QAC3B,OAAO,CAAC,MAAM,GAAG,CAAC;QAClB,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CACjD,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nimbus-dev/sdk v1.0.0 — Plugin API v1 (stable baseline)
|
|
3
|
+
* MIT License
|
|
4
|
+
*
|
|
5
|
+
* Typed scaffolding for building Nimbus extensions (MCP connectors).
|
|
6
|
+
* See CHANGELOG.md for the stable surface guarantee.
|
|
7
|
+
*/
|
|
8
|
+
export type { AuditEmit, AuditLogger } from "./audit-logger";
|
|
9
|
+
export { createScopedAuditLogger } from "./audit-logger";
|
|
10
|
+
export { assertNoRowDataTools, ExtensionContractError, ROW_DATA_TOOL_SEGMENTS, type RowDataToolCandidate, runContractTests, } from "./contract-tests";
|
|
11
|
+
export { type AppStoreConnectJwtParams, signAppStoreConnectJwt, } from "./crypto/app-store-connect-jwt";
|
|
12
|
+
export { canonicalize, canonicalizeManifest, ManifestNestedTooDeep, NonIntegerNumberInManifest, UnsupportedManifestValueType, } from "./crypto/canonical-json";
|
|
13
|
+
export { base64UrlJson, type SignJwtOptions, signJwt } from "./crypto/jwt";
|
|
14
|
+
export { type FetchLike, type GoogleServiceAccount, mintGoogleAccessToken, parseServiceAccountJson, signServiceAccountAssertion, } from "./crypto/service-account-token";
|
|
15
|
+
export type { SignatureDisableReason } from "./crypto/verify-signature";
|
|
16
|
+
export { decodeBase64, encodeBase64, errorToHardDisableReason, generateEd25519Keypair, PublisherKeyMismatch, SignatureInvalid, SignatureInvalidFormat, signManifest, verifyManifestSignature, } from "./crypto/verify-signature";
|
|
17
|
+
export { channelUpgradeHint, type DistributionChannel, type ResolveChannelOptions, resolveDistributionChannel, } from "./distribution-channel";
|
|
18
|
+
export type { HitlRequest } from "./hitl-request";
|
|
19
|
+
export { isHitlRequest } from "./hitl-request";
|
|
20
|
+
export { NimbusExtensionServer } from "./server";
|
|
21
|
+
export { MockGateway } from "./testing/index";
|
|
22
|
+
export type { ExtensionManifest, NimbusItem } from "./types";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,wBAAwB,EAC7B,sBAAsB,GACvB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EACL,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,YAAY,EACZ,uBAAuB,GACxB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nimbus-dev/sdk v1.0.0 — Plugin API v1 (stable baseline)
|
|
3
|
+
* MIT License
|
|
4
|
+
*
|
|
5
|
+
* Typed scaffolding for building Nimbus extensions (MCP connectors).
|
|
6
|
+
* See CHANGELOG.md for the stable surface guarantee.
|
|
7
|
+
*/
|
|
8
|
+
export { createScopedAuditLogger } from "./audit-logger";
|
|
9
|
+
export { assertNoRowDataTools, ExtensionContractError, ROW_DATA_TOOL_SEGMENTS, runContractTests, } from "./contract-tests";
|
|
10
|
+
export { signAppStoreConnectJwt, } from "./crypto/app-store-connect-jwt";
|
|
11
|
+
export { canonicalize, canonicalizeManifest, ManifestNestedTooDeep, NonIntegerNumberInManifest, UnsupportedManifestValueType, } from "./crypto/canonical-json";
|
|
12
|
+
export { base64UrlJson, signJwt } from "./crypto/jwt";
|
|
13
|
+
export { mintGoogleAccessToken, parseServiceAccountJson, signServiceAccountAssertion, } from "./crypto/service-account-token";
|
|
14
|
+
export { decodeBase64, encodeBase64, errorToHardDisableReason, generateEd25519Keypair, PublisherKeyMismatch, SignatureInvalid, SignatureInvalidFormat, signManifest, verifyManifestSignature, } from "./crypto/verify-signature";
|
|
15
|
+
export { channelUpgradeHint, resolveDistributionChannel, } from "./distribution-channel";
|
|
16
|
+
export { isHitlRequest } from "./hitl-request";
|
|
17
|
+
export { NimbusExtensionServer } from "./server";
|
|
18
|
+
export { MockGateway } from "./testing/index";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EAEtB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,sBAAsB,GACvB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAuB,OAAO,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAGL,qBAAqB,EACrB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,YAAY,EACZ,uBAAuB,GACxB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,kBAAkB,EAGlB,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ipc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ipc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,GAEjB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Max bytes per NDJSON line (UTF-8), aligned with IPC protocol limits. */
|
|
2
|
+
export declare const IPC_MAX_LINE_BYTES: number;
|
|
3
|
+
export type NdjsonLineReaderOptions = {
|
|
4
|
+
/** When set, oversized lines throw this type instead of `Error`. */
|
|
5
|
+
lineLimitError?: new (message: string) => Error;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Buffers UTF-8 chunks and emits complete non-empty lines (trailing `\r` stripped).
|
|
9
|
+
* Shared by Gateway JSON-RPC and the CLI IPC client.
|
|
10
|
+
*/
|
|
11
|
+
export declare class NdjsonLineReader {
|
|
12
|
+
private readonly lineLimitCtor;
|
|
13
|
+
private readonly decoder;
|
|
14
|
+
private pending;
|
|
15
|
+
constructor(opts?: NdjsonLineReaderOptions);
|
|
16
|
+
private throwLineTooLong;
|
|
17
|
+
push(chunk: Uint8Array): string[];
|
|
18
|
+
flush(): string[];
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=ndjson-line-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ndjson-line-reader.d.ts","sourceRoot":"","sources":["../../src/ipc/ndjson-line-reader.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,QAAc,CAAC;AAM9C,MAAM,MAAM,uBAAuB,GAAG;IACpC,oEAAoE;IACpE,cAAc,CAAC,EAAE,KACf,OAAO,EAAE,MAAM,KACZ,KAAK,CAAC;CACZ,CAAC;AAEF;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAEnB;IACX,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8C;IACtE,OAAO,CAAC,OAAO,CAAM;gBAET,IAAI,GAAE,uBAA4B;IAI9C,OAAO,CAAC,gBAAgB;IAIxB,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE;IAyBjC,KAAK,IAAI,MAAM,EAAE;CAWlB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Max bytes per NDJSON line (UTF-8), aligned with IPC protocol limits. */
|
|
2
|
+
export const IPC_MAX_LINE_BYTES = 1024 * 1024;
|
|
3
|
+
function byteLengthUtf8(s) {
|
|
4
|
+
return new TextEncoder().encode(s).length;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Buffers UTF-8 chunks and emits complete non-empty lines (trailing `\r` stripped).
|
|
8
|
+
* Shared by Gateway JSON-RPC and the CLI IPC client.
|
|
9
|
+
*/
|
|
10
|
+
export class NdjsonLineReader {
|
|
11
|
+
lineLimitCtor;
|
|
12
|
+
decoder = new TextDecoder("utf-8", { fatal: false });
|
|
13
|
+
pending = "";
|
|
14
|
+
constructor(opts = {}) {
|
|
15
|
+
this.lineLimitCtor = opts.lineLimitError ?? Error;
|
|
16
|
+
}
|
|
17
|
+
throwLineTooLong(message) {
|
|
18
|
+
throw new this.lineLimitCtor(message);
|
|
19
|
+
}
|
|
20
|
+
push(chunk) {
|
|
21
|
+
this.pending += this.decoder.decode(chunk, { stream: true });
|
|
22
|
+
const out = [];
|
|
23
|
+
while (true) {
|
|
24
|
+
const nl = this.pending.indexOf("\n");
|
|
25
|
+
if (nl < 0) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
const line = this.pending.slice(0, nl);
|
|
29
|
+
this.pending = this.pending.slice(nl + 1);
|
|
30
|
+
const trimmed = line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
31
|
+
if (trimmed.length === 0) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (byteLengthUtf8(trimmed) > IPC_MAX_LINE_BYTES) {
|
|
35
|
+
this.throwLineTooLong("Message exceeds 1MB line limit");
|
|
36
|
+
}
|
|
37
|
+
out.push(trimmed);
|
|
38
|
+
}
|
|
39
|
+
if (byteLengthUtf8(this.pending) > IPC_MAX_LINE_BYTES) {
|
|
40
|
+
this.throwLineTooLong("Message exceeds 1MB line limit");
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
flush() {
|
|
45
|
+
const rest = this.pending + this.decoder.decode();
|
|
46
|
+
this.pending = "";
|
|
47
|
+
if (rest.length === 0) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
if (byteLengthUtf8(rest) > IPC_MAX_LINE_BYTES) {
|
|
51
|
+
this.throwLineTooLong("Message exceeds 1MB line limit");
|
|
52
|
+
}
|
|
53
|
+
return [rest.endsWith("\r") ? rest.slice(0, -1) : rest];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=ndjson-line-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ndjson-line-reader.js","sourceRoot":"","sources":["../../src/ipc/ndjson-line-reader.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC5C,CAAC;AASD;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IACV,aAAa,CAEnB;IACM,OAAO,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,OAAO,GAAG,EAAE,CAAC;IAErB,YAAY,OAAgC,EAAE;QAC5C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC;IACpD,CAAC;IAEO,gBAAgB,CAAC,OAAe;QACtC,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,CAAC,KAAiB;QACpB,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBACX,MAAM;YACR,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YACD,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,kBAAkB,EAAE,CAAC;gBACjD,IAAI,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,CAAC;YAC1D,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC;QACD,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,kBAAkB,EAAE,CAAC;YACtD,IAAI,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,kBAAkB,EAAE,CAAC;YAC9C,IAAI,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;CACF"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NimbusExtensionServer — base class for all Nimbus MCP extension servers
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* const server = new NimbusExtensionServer({ manifest, onAuth });
|
|
6
|
+
* server.registerTool("search", { description, inputSchema, handler });
|
|
7
|
+
* server.start();
|
|
8
|
+
*/
|
|
9
|
+
import type { ExtensionManifest } from "./types";
|
|
10
|
+
export interface ExtensionServerOptions<TClient> {
|
|
11
|
+
manifest: ExtensionManifest;
|
|
12
|
+
onAuth?: (ctx: {
|
|
13
|
+
accessToken: string;
|
|
14
|
+
}) => TClient;
|
|
15
|
+
}
|
|
16
|
+
export interface ToolDefinition<TInput, TClient> {
|
|
17
|
+
description: string;
|
|
18
|
+
inputSchema: Record<string, unknown>;
|
|
19
|
+
handler: (input: TInput, ctx: {
|
|
20
|
+
client: TClient;
|
|
21
|
+
}) => Promise<unknown>;
|
|
22
|
+
}
|
|
23
|
+
export declare class NimbusExtensionServer<TClient = unknown> {
|
|
24
|
+
private readonly _options;
|
|
25
|
+
constructor(options: ExtensionServerOptions<TClient>);
|
|
26
|
+
registerTool<TInput>(_name: string, _definition: ToolDefinition<TInput, TClient>): void;
|
|
27
|
+
start(): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,sBAAsB,CAAC,OAAO;IAC7C,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;CACpD;AAED,MAAM,WAAW,cAAc,CAAC,MAAM,EAAE,OAAO;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE;AAED,qBAAa,qBAAqB,CAAC,OAAO,GAAG,OAAO;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;gBAE/C,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC;IAIpD,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIvF,KAAK,IAAI,IAAI;CAKd"}
|