@manifest-network/manifest-mcp-fred 0.1.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/dist/http/auth.d.ts +15 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +23 -0
- package/dist/http/auth.js.map +1 -0
- package/dist/http/fred.d.ts +74 -0
- package/dist/http/fred.d.ts.map +1 -0
- package/dist/http/fred.js +94 -0
- package/dist/http/fred.js.map +1 -0
- package/dist/http/provider.d.ts +52 -0
- package/dist/http/provider.d.ts.map +1 -0
- package/dist/http/provider.js +88 -0
- package/dist/http/provider.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +211 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +44 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +122 -0
- package/dist/manifest.js.map +1 -0
- package/dist/tools/appStatus.d.ts +21 -0
- package/dist/tools/appStatus.d.ts.map +1 -0
- package/dist/tools/appStatus.js +73 -0
- package/dist/tools/appStatus.js.map +1 -0
- package/dist/tools/browseCatalog.d.ts +27 -0
- package/dist/tools/browseCatalog.d.ts.map +1 -0
- package/dist/tools/browseCatalog.js +76 -0
- package/dist/tools/browseCatalog.js.map +1 -0
- package/dist/tools/deployApp.d.ts +65 -0
- package/dist/tools/deployApp.d.ts.map +1 -0
- package/dist/tools/deployApp.js +143 -0
- package/dist/tools/deployApp.js.map +1 -0
- package/dist/tools/fetchActiveLease.d.ts +12 -0
- package/dist/tools/fetchActiveLease.d.ts.map +1 -0
- package/dist/tools/fetchActiveLease.js +17 -0
- package/dist/tools/fetchActiveLease.js.map +1 -0
- package/dist/tools/getLogs.d.ts +11 -0
- package/dist/tools/getLogs.d.ts.map +1 -0
- package/dist/tools/getLogs.js +32 -0
- package/dist/tools/getLogs.js.map +1 -0
- package/dist/tools/resolveLeaseProvider.d.ts +7 -0
- package/dist/tools/resolveLeaseProvider.d.ts.map +1 -0
- package/dist/tools/resolveLeaseProvider.js +20 -0
- package/dist/tools/resolveLeaseProvider.js.map +1 -0
- package/dist/tools/restartApp.d.ts +10 -0
- package/dist/tools/restartApp.d.ts.map +1 -0
- package/dist/tools/restartApp.js +14 -0
- package/dist/tools/restartApp.js.map +1 -0
- package/dist/tools/updateApp.d.ts +10 -0
- package/dist/tools/updateApp.d.ts.map +1 -0
- package/dist/tools/updateApp.js +47 -0
- package/dist/tools/updateApp.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/http/auth.d.ts
|
|
2
|
+
declare function createSignMessage(tenant: string, leaseUuid: string, timestamp: number): string;
|
|
3
|
+
declare function createLeaseDataSignMessage(leaseUuid: string, metaHashHex: string, timestamp: number): string;
|
|
4
|
+
interface AuthTokenPayload {
|
|
5
|
+
readonly tenant: string;
|
|
6
|
+
readonly lease_uuid: string;
|
|
7
|
+
readonly timestamp: number;
|
|
8
|
+
readonly pub_key: string;
|
|
9
|
+
readonly signature: string;
|
|
10
|
+
readonly meta_hash?: string;
|
|
11
|
+
}
|
|
12
|
+
declare function createAuthToken(tenant: string, leaseUuid: string, timestamp: number, pubKey: string, signature: string, metaHashHex?: string): string;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { AuthTokenPayload, createAuthToken, createLeaseDataSignMessage, createSignMessage };
|
|
15
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","names":[],"sources":["../../src/http/auth.ts"],"mappings":";iBAEgB,iBAAA,CACd,MAAA,UACA,SAAA,UACA,SAAA;AAAA,iBAKc,0BAAA,CACd,SAAA,UACA,WAAA,UACA,SAAA;AAAA,UAKe,gBAAA;EAAA,SACN,MAAA;EAAA,SACA,UAAA;EAAA,SACA,SAAA;EAAA,SACA,OAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;AAAA;AAAA,iBAGK,eAAA,CACd,MAAA,UACA,SAAA,UACA,SAAA,UACA,MAAA,UACA,SAAA,UACA,WAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { toBase64 } from "@cosmjs/encoding";
|
|
2
|
+
//#region src/http/auth.ts
|
|
3
|
+
function createSignMessage(tenant, leaseUuid, timestamp) {
|
|
4
|
+
return `${tenant}:${leaseUuid}:${timestamp}`;
|
|
5
|
+
}
|
|
6
|
+
function createLeaseDataSignMessage(leaseUuid, metaHashHex, timestamp) {
|
|
7
|
+
return `manifest lease data ${leaseUuid} ${metaHashHex} ${timestamp}`;
|
|
8
|
+
}
|
|
9
|
+
function createAuthToken(tenant, leaseUuid, timestamp, pubKey, signature, metaHashHex) {
|
|
10
|
+
const payload = {
|
|
11
|
+
tenant,
|
|
12
|
+
lease_uuid: leaseUuid,
|
|
13
|
+
timestamp,
|
|
14
|
+
pub_key: pubKey,
|
|
15
|
+
signature,
|
|
16
|
+
...metaHashHex !== void 0 && { meta_hash: metaHashHex }
|
|
17
|
+
};
|
|
18
|
+
return toBase64(new TextEncoder().encode(JSON.stringify(payload)));
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { createAuthToken, createLeaseDataSignMessage, createSignMessage };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","names":[],"sources":["../../src/http/auth.ts"],"sourcesContent":["import { toBase64 } from '@cosmjs/encoding';\n\nexport function createSignMessage(\n tenant: string,\n leaseUuid: string,\n timestamp: number,\n): string {\n return `${tenant}:${leaseUuid}:${timestamp}`;\n}\n\nexport function createLeaseDataSignMessage(\n leaseUuid: string,\n metaHashHex: string,\n timestamp: number,\n): string {\n return `manifest lease data ${leaseUuid} ${metaHashHex} ${timestamp}`;\n}\n\nexport interface AuthTokenPayload {\n readonly tenant: string;\n readonly lease_uuid: string;\n readonly timestamp: number;\n readonly pub_key: string;\n readonly signature: string;\n readonly meta_hash?: string;\n}\n\nexport function createAuthToken(\n tenant: string,\n leaseUuid: string,\n timestamp: number,\n pubKey: string,\n signature: string,\n metaHashHex?: string,\n): string {\n const payload: AuthTokenPayload = {\n tenant,\n lease_uuid: leaseUuid,\n timestamp,\n pub_key: pubKey,\n signature,\n ...(metaHashHex !== undefined && { meta_hash: metaHashHex }),\n };\n return toBase64(new TextEncoder().encode(JSON.stringify(payload)));\n}\n"],"mappings":";;AAEA,SAAgB,kBACd,QACA,WACA,WACQ;AACR,QAAO,GAAG,OAAO,GAAG,UAAU,GAAG;;AAGnC,SAAgB,2BACd,WACA,aACA,WACQ;AACR,QAAO,uBAAuB,UAAU,GAAG,YAAY,GAAG;;AAY5D,SAAgB,gBACd,QACA,WACA,WACA,QACA,WACA,aACQ;CACR,MAAM,UAA4B;EAChC;EACA,YAAY;EACZ;EACA,SAAS;EACT;EACA,GAAI,gBAAgB,KAAA,KAAa,EAAE,WAAW,aAAa;EAC5D;AACD,QAAO,SAAS,IAAI,aAAa,CAAC,OAAO,KAAK,UAAU,QAAQ,CAAC,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { LeaseState } from "@manifest-network/manifest-mcp-core";
|
|
2
|
+
|
|
3
|
+
//#region src/http/fred.d.ts
|
|
4
|
+
declare const MAX_TAIL = 1000;
|
|
5
|
+
interface FredInstanceInfo {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly status: string;
|
|
8
|
+
readonly ports?: Record<string, number>;
|
|
9
|
+
readonly fqdn?: string;
|
|
10
|
+
}
|
|
11
|
+
interface FredServiceStatus {
|
|
12
|
+
readonly instances: readonly FredInstanceInfo[];
|
|
13
|
+
}
|
|
14
|
+
interface FredLeaseStatus {
|
|
15
|
+
readonly state: LeaseState;
|
|
16
|
+
readonly provision_status?: string;
|
|
17
|
+
readonly phase?: string;
|
|
18
|
+
readonly steps?: Record<string, string>;
|
|
19
|
+
readonly instances?: readonly FredInstanceInfo[];
|
|
20
|
+
readonly endpoints?: Record<string, string>;
|
|
21
|
+
readonly last_error?: string;
|
|
22
|
+
readonly fail_count?: number;
|
|
23
|
+
readonly created_at?: string;
|
|
24
|
+
readonly services?: Record<string, FredServiceStatus>;
|
|
25
|
+
}
|
|
26
|
+
declare function getLeaseStatus(providerUrl: string, leaseUuid: string, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<FredLeaseStatus>;
|
|
27
|
+
interface FredLeaseLogs {
|
|
28
|
+
readonly lease_uuid: string;
|
|
29
|
+
readonly tenant: string;
|
|
30
|
+
readonly provider_uuid: string;
|
|
31
|
+
readonly logs: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
declare function getLeaseLogs(providerUrl: string, leaseUuid: string, authToken: string, tail?: number, fetchFn?: typeof globalThis.fetch): Promise<FredLeaseLogs>;
|
|
34
|
+
interface FredLeaseProvision {
|
|
35
|
+
readonly status: string;
|
|
36
|
+
readonly fail_count: number;
|
|
37
|
+
readonly last_error: string;
|
|
38
|
+
}
|
|
39
|
+
declare function getLeaseProvision(providerUrl: string, leaseUuid: string, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<FredLeaseProvision>;
|
|
40
|
+
interface FredActionResponse {
|
|
41
|
+
readonly status: string;
|
|
42
|
+
}
|
|
43
|
+
declare function restartLease(providerUrl: string, leaseUuid: string, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<FredActionResponse>;
|
|
44
|
+
declare function updateLease(providerUrl: string, leaseUuid: string, payload: Uint8Array, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<FredActionResponse>;
|
|
45
|
+
interface FredLeaseRelease {
|
|
46
|
+
readonly version: number;
|
|
47
|
+
readonly image: string;
|
|
48
|
+
readonly status: string;
|
|
49
|
+
readonly created_at: string;
|
|
50
|
+
readonly error?: string;
|
|
51
|
+
readonly manifest?: string;
|
|
52
|
+
}
|
|
53
|
+
interface FredLeaseReleases {
|
|
54
|
+
readonly lease_uuid: string;
|
|
55
|
+
readonly tenant: string;
|
|
56
|
+
readonly provider_uuid: string;
|
|
57
|
+
readonly releases: readonly FredLeaseRelease[];
|
|
58
|
+
}
|
|
59
|
+
declare function getLeaseReleases(providerUrl: string, leaseUuid: string, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<FredLeaseReleases>;
|
|
60
|
+
interface FredLeaseInfo {
|
|
61
|
+
readonly host: string;
|
|
62
|
+
readonly ports?: Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
declare function getLeaseInfo(providerUrl: string, leaseUuid: string, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<FredLeaseInfo>;
|
|
65
|
+
interface PollOptions {
|
|
66
|
+
readonly intervalMs?: number;
|
|
67
|
+
readonly timeoutMs?: number;
|
|
68
|
+
readonly abortSignal?: AbortSignal;
|
|
69
|
+
readonly onProgress?: (status: FredLeaseStatus) => void;
|
|
70
|
+
}
|
|
71
|
+
declare function pollLeaseUntilReady(providerUrl: string, leaseUuid: string, authToken: string | (() => Promise<string>), opts?: PollOptions, fetchFn?: typeof globalThis.fetch): Promise<FredLeaseStatus>;
|
|
72
|
+
//#endregion
|
|
73
|
+
export { FredActionResponse, FredInstanceInfo, FredLeaseInfo, FredLeaseLogs, FredLeaseProvision, FredLeaseRelease, FredLeaseReleases, FredLeaseStatus, FredServiceStatus, MAX_TAIL, PollOptions, getLeaseInfo, getLeaseLogs, getLeaseProvision, getLeaseReleases, getLeaseStatus, pollLeaseUntilReady, restartLease, updateLease };
|
|
74
|
+
//# sourceMappingURL=fred.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fred.d.ts","names":[],"sources":["../../src/http/fred.ts"],"mappings":";;;cAYa,QAAA;AAAA,UAEI,gBAAA;EAAA,SACN,IAAA;EAAA,SACA,MAAA;EAAA,SACA,KAAA,GAAQ,MAAA;EAAA,SACR,IAAA;AAAA;AAAA,UAGM,iBAAA;EAAA,SACN,SAAA,WAAoB,gBAAA;AAAA;AAAA,UAGd,eAAA;EAAA,SACN,KAAA,EAAO,UAAA;EAAA,SACP,gBAAA;EAAA,SACA,KAAA;EAAA,SACA,KAAA,GAAQ,MAAA;EAAA,SACR,SAAA,YAAqB,gBAAA;EAAA,SACrB,SAAA,GAAY,MAAA;EAAA,SACZ,UAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA,GAAW,MAAA,SAAe,iBAAA;AAAA;AAAA,iBAQf,cAAA,CACpB,WAAA,UACA,SAAA,UACA,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,eAAA;AAAA,UAsBM,aAAA;EAAA,SACN,UAAA;EAAA,SACA,MAAA;EAAA,SACA,aAAA;EAAA,SACA,IAAA,EAAM,MAAA;AAAA;AAAA,iBAGK,YAAA,CACpB,WAAA,UACA,SAAA,UACA,SAAA,UACA,IAAA,WACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,aAAA;AAAA,UAgBM,kBAAA;EAAA,SACN,MAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;AAAA;AAAA,iBAGW,iBAAA,CACpB,WAAA,UACA,SAAA,UACA,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,kBAAA;AAAA,UAcM,kBAAA;EAAA,SACN,MAAA;AAAA;AAAA,iBAGW,YAAA,CACpB,WAAA,UACA,SAAA,UACA,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,kBAAA;AAAA,iBAeW,WAAA,CACpB,WAAA,UACA,SAAA,UACA,OAAA,EAAS,UAAA,EACT,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,kBAAA;AAAA,UAmBM,gBAAA;EAAA,SACN,OAAA;EAAA,SACA,KAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;EAAA,SACA,KAAA;EAAA,SACA,QAAA;AAAA;AAAA,UAGM,iBAAA;EAAA,SACN,UAAA;EAAA,SACA,MAAA;EAAA,SACA,aAAA;EAAA,SACA,QAAA,WAAmB,gBAAA;AAAA;AAAA,iBAGR,gBAAA,CACpB,WAAA,UACA,SAAA,UACA,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,iBAAA;AAAA,UAcM,aAAA;EAAA,SACN,IAAA;EAAA,SACA,KAAA,GAAQ,MAAA;AAAA;AAAA,iBAGG,YAAA,CACpB,WAAA,UACA,SAAA,UACA,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,aAAA;AAAA,UAcM,WAAA;EAAA,SACN,UAAA;EAAA,SACA,SAAA;EAAA,SACA,WAAA,GAAc,WAAA;EAAA,SACd,UAAA,IAAc,MAAA,EAAQ,eAAA;AAAA;AAAA,iBA0BX,mBAAA,CACpB,WAAA,UACA,SAAA,UACA,SAAA,kBAA2B,OAAA,WAC3B,IAAA,GAAM,WAAA,EACN,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,eAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ProviderApiError, checkedFetch, parseJsonResponse, validateProviderUrl } from "./provider.js";
|
|
2
|
+
import { LeaseState, leaseStateFromJSON, logger } from "@manifest-network/manifest-mcp-core";
|
|
3
|
+
//#region src/http/fred.ts
|
|
4
|
+
const MAX_TAIL = 1e3;
|
|
5
|
+
async function getLeaseStatus(providerUrl, leaseUuid, authToken, fetchFn) {
|
|
6
|
+
const url = `${validateProviderUrl(providerUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/status`;
|
|
7
|
+
const raw = await parseJsonResponse(await checkedFetch(url, { headers: { Authorization: `Bearer ${authToken}` } }, void 0, fetchFn), url);
|
|
8
|
+
const state = leaseStateFromJSON(raw.state);
|
|
9
|
+
if (state === LeaseState.UNRECOGNIZED) logger.warn(`[getLeaseStatus] Unrecognized lease state "${raw.state}" for lease ${leaseUuid}. The provider may be running a newer version than the client supports.`);
|
|
10
|
+
return {
|
|
11
|
+
...raw,
|
|
12
|
+
state
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function getLeaseLogs(providerUrl, leaseUuid, authToken, tail, fetchFn) {
|
|
16
|
+
const validated = validateProviderUrl(providerUrl);
|
|
17
|
+
const cappedTail = tail !== void 0 ? Math.min(tail, MAX_TAIL) : void 0;
|
|
18
|
+
const qs = cappedTail !== void 0 ? `?tail=${cappedTail}` : "";
|
|
19
|
+
const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/logs${qs}`;
|
|
20
|
+
return await parseJsonResponse(await checkedFetch(url, { headers: { Authorization: `Bearer ${authToken}` } }, void 0, fetchFn), url);
|
|
21
|
+
}
|
|
22
|
+
async function getLeaseProvision(providerUrl, leaseUuid, authToken, fetchFn) {
|
|
23
|
+
const url = `${validateProviderUrl(providerUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/provision`;
|
|
24
|
+
return await parseJsonResponse(await checkedFetch(url, { headers: { Authorization: `Bearer ${authToken}` } }, void 0, fetchFn), url);
|
|
25
|
+
}
|
|
26
|
+
async function restartLease(providerUrl, leaseUuid, authToken, fetchFn) {
|
|
27
|
+
const url = `${validateProviderUrl(providerUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/restart`;
|
|
28
|
+
return await parseJsonResponse(await checkedFetch(url, {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: { Authorization: `Bearer ${authToken}` }
|
|
31
|
+
}, void 0, fetchFn), url);
|
|
32
|
+
}
|
|
33
|
+
async function updateLease(providerUrl, leaseUuid, payload, authToken, fetchFn) {
|
|
34
|
+
const url = `${validateProviderUrl(providerUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/update`;
|
|
35
|
+
return await parseJsonResponse(await checkedFetch(url, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
Authorization: `Bearer ${authToken}`,
|
|
39
|
+
"Content-Type": "application/octet-stream"
|
|
40
|
+
},
|
|
41
|
+
body: payload
|
|
42
|
+
}, void 0, fetchFn), url);
|
|
43
|
+
}
|
|
44
|
+
async function getLeaseReleases(providerUrl, leaseUuid, authToken, fetchFn) {
|
|
45
|
+
const url = `${validateProviderUrl(providerUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/releases`;
|
|
46
|
+
return await parseJsonResponse(await checkedFetch(url, { headers: { Authorization: `Bearer ${authToken}` } }, void 0, fetchFn), url);
|
|
47
|
+
}
|
|
48
|
+
async function getLeaseInfo(providerUrl, leaseUuid, authToken, fetchFn) {
|
|
49
|
+
const url = `${validateProviderUrl(providerUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/info`;
|
|
50
|
+
return await parseJsonResponse(await checkedFetch(url, { headers: { Authorization: `Bearer ${authToken}` } }, void 0, fetchFn), url);
|
|
51
|
+
}
|
|
52
|
+
function leaseStateName(state) {
|
|
53
|
+
return LeaseState[state] ?? String(state);
|
|
54
|
+
}
|
|
55
|
+
function abortableSleep(ms, signal) {
|
|
56
|
+
if (!signal) return new Promise((resolve) => setTimeout(resolve, ms));
|
|
57
|
+
signal.throwIfAborted();
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const onAbort = () => {
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
reject(signal.reason ?? new DOMException("The operation was aborted", "AbortError"));
|
|
62
|
+
};
|
|
63
|
+
const timer = setTimeout(() => {
|
|
64
|
+
signal.removeEventListener("abort", onAbort);
|
|
65
|
+
resolve();
|
|
66
|
+
}, ms);
|
|
67
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function pollLeaseUntilReady(providerUrl, leaseUuid, authToken, opts = {}, fetchFn) {
|
|
71
|
+
const { intervalMs = 3e3, timeoutMs = 12e4, abortSignal, onProgress } = opts;
|
|
72
|
+
const deadline = Date.now() + timeoutMs;
|
|
73
|
+
let lastState;
|
|
74
|
+
while (Date.now() < deadline) {
|
|
75
|
+
abortSignal?.throwIfAborted();
|
|
76
|
+
const status = await getLeaseStatus(providerUrl, leaseUuid, typeof authToken === "function" ? await authToken() : authToken, fetchFn);
|
|
77
|
+
lastState = status.state;
|
|
78
|
+
onProgress?.(status);
|
|
79
|
+
switch (status.state) {
|
|
80
|
+
case LeaseState.LEASE_STATE_ACTIVE: return status;
|
|
81
|
+
case LeaseState.LEASE_STATE_PENDING: break;
|
|
82
|
+
case LeaseState.LEASE_STATE_CLOSED:
|
|
83
|
+
case LeaseState.LEASE_STATE_REJECTED:
|
|
84
|
+
case LeaseState.LEASE_STATE_EXPIRED: throw new ProviderApiError(0, `Lease ${leaseUuid} entered terminal state ${leaseStateName(status.state)}`);
|
|
85
|
+
default: throw new ProviderApiError(0, `Lease ${leaseUuid} returned unexpected state ${leaseStateName(status.state)}`);
|
|
86
|
+
}
|
|
87
|
+
await abortableSleep(intervalMs, abortSignal);
|
|
88
|
+
}
|
|
89
|
+
throw new ProviderApiError(0, `Lease ${leaseUuid} poll timed out after ${timeoutMs}ms (last state: ${lastState !== void 0 ? leaseStateName(lastState) : "unknown"})`);
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { MAX_TAIL, getLeaseInfo, getLeaseLogs, getLeaseProvision, getLeaseReleases, getLeaseStatus, pollLeaseUntilReady, restartLease, updateLease };
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=fred.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fred.js","names":[],"sources":["../../src/http/fred.ts"],"sourcesContent":["import {\n LeaseState,\n leaseStateFromJSON,\n logger,\n} from '@manifest-network/manifest-mcp-core';\nimport {\n checkedFetch,\n ProviderApiError,\n parseJsonResponse,\n validateProviderUrl,\n} from './provider.js';\n\nexport const MAX_TAIL = 1000;\n\nexport interface FredInstanceInfo {\n readonly name: string;\n readonly status: string;\n readonly ports?: Record<string, number>;\n readonly fqdn?: string;\n}\n\nexport interface FredServiceStatus {\n readonly instances: readonly FredInstanceInfo[];\n}\n\nexport interface FredLeaseStatus {\n readonly state: LeaseState;\n readonly provision_status?: string;\n readonly phase?: string;\n readonly steps?: Record<string, string>;\n readonly instances?: readonly FredInstanceInfo[];\n readonly endpoints?: Record<string, string>;\n readonly last_error?: string;\n readonly fail_count?: number;\n readonly created_at?: string;\n readonly services?: Record<string, FredServiceStatus>;\n}\n\n/** Raw wire shape before LeaseState conversion */\ninterface RawLeaseStatus extends Omit<FredLeaseStatus, 'state'> {\n readonly state: string;\n}\n\nexport async function getLeaseStatus(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseStatus> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/status`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n const raw = await parseJsonResponse<RawLeaseStatus>(res, url);\n const state = leaseStateFromJSON(raw.state);\n if (state === LeaseState.UNRECOGNIZED) {\n logger.warn(\n `[getLeaseStatus] Unrecognized lease state \"${raw.state}\" for lease ${leaseUuid}. ` +\n 'The provider may be running a newer version than the client supports.',\n );\n }\n return { ...raw, state };\n}\n\nexport interface FredLeaseLogs {\n readonly lease_uuid: string;\n readonly tenant: string;\n readonly provider_uuid: string;\n readonly logs: Record<string, string>;\n}\n\nexport async function getLeaseLogs(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n tail?: number,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseLogs> {\n const validated = validateProviderUrl(providerUrl);\n const cappedTail = tail !== undefined ? Math.min(tail, MAX_TAIL) : undefined;\n const qs = cappedTail !== undefined ? `?tail=${cappedTail}` : '';\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/logs${qs}`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseLogs>(res, url);\n}\n\nexport interface FredLeaseProvision {\n readonly status: string;\n readonly fail_count: number;\n readonly last_error: string;\n}\n\nexport async function getLeaseProvision(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseProvision> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/provision`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseProvision>(res, url);\n}\n\nexport interface FredActionResponse {\n readonly status: string;\n}\n\nexport async function restartLease(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredActionResponse> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/restart`;\n const res = await checkedFetch(\n url,\n {\n method: 'POST',\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredActionResponse>(res, url);\n}\n\nexport async function updateLease(\n providerUrl: string,\n leaseUuid: string,\n payload: Uint8Array,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredActionResponse> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/update`;\n const res = await checkedFetch(\n url,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/octet-stream',\n },\n body: payload,\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredActionResponse>(res, url);\n}\n\nexport interface FredLeaseRelease {\n readonly version: number;\n readonly image: string;\n readonly status: string;\n readonly created_at: string;\n readonly error?: string;\n readonly manifest?: string;\n}\n\nexport interface FredLeaseReleases {\n readonly lease_uuid: string;\n readonly tenant: string;\n readonly provider_uuid: string;\n readonly releases: readonly FredLeaseRelease[];\n}\n\nexport async function getLeaseReleases(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseReleases> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/releases`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseReleases>(res, url);\n}\n\nexport interface FredLeaseInfo {\n readonly host: string;\n readonly ports?: Record<string, unknown>;\n}\n\nexport async function getLeaseInfo(\n providerUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseInfo> {\n const validated = validateProviderUrl(providerUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/info`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<FredLeaseInfo>(res, url);\n}\n\nexport interface PollOptions {\n readonly intervalMs?: number;\n readonly timeoutMs?: number;\n readonly abortSignal?: AbortSignal;\n readonly onProgress?: (status: FredLeaseStatus) => void;\n}\n\nfunction leaseStateName(state: LeaseState): string {\n return LeaseState[state] ?? String(state);\n}\n\nfunction abortableSleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (!signal) return new Promise((resolve) => setTimeout(resolve, ms));\n signal.throwIfAborted();\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(\n signal.reason ??\n new DOMException('The operation was aborted', 'AbortError'),\n );\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nexport async function pollLeaseUntilReady(\n providerUrl: string,\n leaseUuid: string,\n authToken: string | (() => Promise<string>),\n opts: PollOptions = {},\n fetchFn?: typeof globalThis.fetch,\n): Promise<FredLeaseStatus> {\n const {\n intervalMs = 3_000,\n timeoutMs = 120_000,\n abortSignal,\n onProgress,\n } = opts;\n const deadline = Date.now() + timeoutMs;\n let lastState: LeaseState | undefined;\n\n while (Date.now() < deadline) {\n abortSignal?.throwIfAborted();\n const token =\n typeof authToken === 'function' ? await authToken() : authToken;\n const status = await getLeaseStatus(providerUrl, leaseUuid, token, fetchFn);\n lastState = status.state;\n onProgress?.(status);\n switch (status.state) {\n case LeaseState.LEASE_STATE_ACTIVE:\n return status;\n case LeaseState.LEASE_STATE_PENDING:\n break;\n case LeaseState.LEASE_STATE_CLOSED:\n case LeaseState.LEASE_STATE_REJECTED:\n case LeaseState.LEASE_STATE_EXPIRED:\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} entered terminal state ${leaseStateName(status.state)}`,\n );\n default:\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} returned unexpected state ${leaseStateName(status.state)}`,\n );\n }\n await abortableSleep(intervalMs, abortSignal);\n }\n\n throw new ProviderApiError(\n 0,\n `Lease ${leaseUuid} poll timed out after ${timeoutMs}ms (last state: ${lastState !== undefined ? leaseStateName(lastState) : 'unknown'})`,\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/http/provider.d.ts
|
|
2
|
+
declare class ProviderApiError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
constructor(status: number, message: string);
|
|
5
|
+
}
|
|
6
|
+
declare function validateProviderUrl(url: string): string;
|
|
7
|
+
declare function checkedFetch(url: string, init?: RequestInit, timeoutMs?: number, fetchFn?: typeof globalThis.fetch): Promise<Response>;
|
|
8
|
+
declare function parseJsonResponse<T>(res: Response, url: string): Promise<T>;
|
|
9
|
+
interface ProviderHealthResponse {
|
|
10
|
+
readonly status: string;
|
|
11
|
+
readonly provider_uuid: string;
|
|
12
|
+
readonly checks?: {
|
|
13
|
+
readonly chain?: {
|
|
14
|
+
readonly status: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
declare function getProviderHealth(providerApiUrl: string, timeoutMs?: number, fetchFn?: typeof globalThis.fetch): Promise<ProviderHealthResponse>;
|
|
19
|
+
interface InstanceInfo {
|
|
20
|
+
readonly instance_index: number;
|
|
21
|
+
readonly container_id: string;
|
|
22
|
+
readonly image: string;
|
|
23
|
+
readonly status: string;
|
|
24
|
+
readonly ports?: Record<string, unknown>;
|
|
25
|
+
readonly fqdn?: string;
|
|
26
|
+
}
|
|
27
|
+
interface ServiceConnectionDetails {
|
|
28
|
+
readonly host?: string;
|
|
29
|
+
readonly fqdn?: string;
|
|
30
|
+
readonly ports?: Record<string, unknown>;
|
|
31
|
+
readonly instances?: readonly InstanceInfo[];
|
|
32
|
+
}
|
|
33
|
+
interface ConnectionDetails {
|
|
34
|
+
readonly host: string;
|
|
35
|
+
readonly fqdn?: string;
|
|
36
|
+
readonly ports?: Record<string, unknown>;
|
|
37
|
+
readonly instances?: readonly InstanceInfo[];
|
|
38
|
+
readonly protocol?: string;
|
|
39
|
+
readonly metadata?: Record<string, string>;
|
|
40
|
+
readonly services?: Record<string, ServiceConnectionDetails>;
|
|
41
|
+
}
|
|
42
|
+
interface LeaseConnectionResponse {
|
|
43
|
+
readonly lease_uuid: string;
|
|
44
|
+
readonly tenant: string;
|
|
45
|
+
readonly provider_uuid: string;
|
|
46
|
+
readonly connection: ConnectionDetails;
|
|
47
|
+
}
|
|
48
|
+
declare function getLeaseConnectionInfo(providerApiUrl: string, leaseUuid: string, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<LeaseConnectionResponse>;
|
|
49
|
+
declare function uploadLeaseData(providerApiUrl: string, leaseUuid: string, payload: Uint8Array, authToken: string, fetchFn?: typeof globalThis.fetch): Promise<void>;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { ConnectionDetails, InstanceInfo, LeaseConnectionResponse, ProviderApiError, ProviderHealthResponse, ServiceConnectionDetails, checkedFetch, getLeaseConnectionInfo, getProviderHealth, parseJsonResponse, uploadLeaseData, validateProviderUrl };
|
|
52
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/http/provider.ts"],"mappings":";cAAa,gBAAA,SAAyB,KAAA;EAAA,SACpB,MAAA;cAEJ,MAAA,UAAgB,OAAA;AAAA;AAAA,iBAUd,mBAAA,CAAoB,GAAA;AAAA,iBAwBd,YAAA,CACpB,GAAA,UACA,IAAA,GAAO,WAAA,EACP,SAAA,WACA,OAAA,UAAgB,UAAA,CAAW,KAAA,GAC1B,OAAA,CAAQ,QAAA;AAAA,iBA4CW,iBAAA,GAAA,CACpB,GAAA,EAAK,QAAA,EACL,GAAA,WACC,OAAA,CAAQ,CAAA;AAAA,UAcM,sBAAA;EAAA,SACN,MAAA;EAAA,SACA,aAAA;EAAA,SACA,MAAA;IAAA,SACE,KAAA;MAAA,SAAmB,MAAA;IAAA;EAAA;AAAA;AAAA,iBAIV,iBAAA,CACpB,cAAA,UACA,SAAA,WACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,sBAAA;AAAA,UAOM,YAAA;EAAA,SACN,cAAA;EAAA,SACA,YAAA;EAAA,SACA,KAAA;EAAA,SACA,MAAA;EAAA,SACA,KAAA,GAAQ,MAAA;EAAA,SACR,IAAA;AAAA;AAAA,UAGM,wBAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA,GAAQ,MAAA;EAAA,SACR,SAAA,YAAqB,YAAA;AAAA;AAAA,UAGf,iBAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA,GAAQ,MAAA;EAAA,SACR,SAAA,YAAqB,YAAA;EAAA,SACrB,QAAA;EAAA,SACA,QAAA,GAAW,MAAA;EAAA,SACX,QAAA,GAAW,MAAA,SAAe,wBAAA;AAAA;AAAA,UAGpB,uBAAA;EAAA,SACN,UAAA;EAAA,SACA,MAAA;EAAA,SACA,aAAA;EAAA,SACA,UAAA,EAAY,iBAAA;AAAA;AAAA,iBAGD,sBAAA,CACpB,cAAA,UACA,SAAA,UACA,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA,CAAQ,uBAAA;AAAA,iBAcW,eAAA,CACpB,cAAA,UACA,SAAA,UACA,OAAA,EAAS,UAAA,EACT,SAAA,UACA,OAAA,UAAiB,UAAA,CAAW,KAAA,GAC3B,OAAA"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
//#region src/http/provider.ts
|
|
2
|
+
var ProviderApiError = class ProviderApiError extends Error {
|
|
3
|
+
constructor(status, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "ProviderApiError";
|
|
6
|
+
this.status = status;
|
|
7
|
+
Object.setPrototypeOf(this, ProviderApiError.prototype);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const LOCALHOST_HOSTS = new Set([
|
|
11
|
+
"localhost",
|
|
12
|
+
"127.0.0.1",
|
|
13
|
+
"[::1]"
|
|
14
|
+
]);
|
|
15
|
+
function validateProviderUrl(url) {
|
|
16
|
+
let parsed;
|
|
17
|
+
try {
|
|
18
|
+
parsed = new URL(url);
|
|
19
|
+
} catch {
|
|
20
|
+
throw new ProviderApiError(0, `Invalid provider URL: ${url}`);
|
|
21
|
+
}
|
|
22
|
+
if (parsed.protocol === "https:") return url.replace(/\/+$/, "");
|
|
23
|
+
if (parsed.protocol === "http:" && LOCALHOST_HOSTS.has(parsed.hostname)) return url.replace(/\/+$/, "");
|
|
24
|
+
throw new ProviderApiError(0, `Provider URL must use HTTPS (or HTTP for localhost): ${url}`);
|
|
25
|
+
}
|
|
26
|
+
const DEFAULT_FETCH_TIMEOUT_MS = 3e4;
|
|
27
|
+
async function checkedFetch(url, init, timeoutMs = DEFAULT_FETCH_TIMEOUT_MS, fetchFn = globalThis.fetch) {
|
|
28
|
+
const callerProvidedSignal = init?.signal != null;
|
|
29
|
+
let controller;
|
|
30
|
+
let timer;
|
|
31
|
+
if (!callerProvidedSignal && timeoutMs > 0) {
|
|
32
|
+
const ctrl = new AbortController();
|
|
33
|
+
controller = ctrl;
|
|
34
|
+
timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
35
|
+
init = {
|
|
36
|
+
...init,
|
|
37
|
+
signal: ctrl.signal
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
let res;
|
|
41
|
+
try {
|
|
42
|
+
res = await fetchFn(url, init);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
45
|
+
if (controller && !callerProvidedSignal) throw new ProviderApiError(0, `Request to ${url} timed out after ${timeoutMs}ms`);
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
throw new ProviderApiError(0, `Network request to ${url} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
49
|
+
} finally {
|
|
50
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
51
|
+
}
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
const body = await res.text().catch((readErr) => `[body read failed: ${readErr instanceof Error ? readErr.message : String(readErr)}]`);
|
|
54
|
+
throw new ProviderApiError(res.status, body || `HTTP ${res.status}`);
|
|
55
|
+
}
|
|
56
|
+
return res;
|
|
57
|
+
}
|
|
58
|
+
async function parseJsonResponse(res, url) {
|
|
59
|
+
const text = await res.text();
|
|
60
|
+
try {
|
|
61
|
+
return JSON.parse(text);
|
|
62
|
+
} catch (parseErr) {
|
|
63
|
+
const reason = parseErr instanceof Error ? parseErr.message : "parse failed";
|
|
64
|
+
throw new ProviderApiError(res.status, `Invalid JSON from ${url} (${reason}): ${text.slice(0, 200)}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function getProviderHealth(providerApiUrl, timeoutMs = 5e3, fetchFn) {
|
|
68
|
+
const url = `${validateProviderUrl(providerApiUrl)}/health`;
|
|
69
|
+
return await parseJsonResponse(await checkedFetch(url, void 0, timeoutMs, fetchFn), url);
|
|
70
|
+
}
|
|
71
|
+
async function getLeaseConnectionInfo(providerApiUrl, leaseUuid, authToken, fetchFn) {
|
|
72
|
+
const url = `${validateProviderUrl(providerApiUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/connection`;
|
|
73
|
+
return await parseJsonResponse(await checkedFetch(url, { headers: { Authorization: `Bearer ${authToken}` } }, void 0, fetchFn), url);
|
|
74
|
+
}
|
|
75
|
+
async function uploadLeaseData(providerApiUrl, leaseUuid, payload, authToken, fetchFn) {
|
|
76
|
+
await checkedFetch(`${validateProviderUrl(providerApiUrl)}/v1/leases/${encodeURIComponent(leaseUuid)}/data`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: {
|
|
79
|
+
Authorization: `Bearer ${authToken}`,
|
|
80
|
+
"Content-Type": "application/octet-stream"
|
|
81
|
+
},
|
|
82
|
+
body: payload
|
|
83
|
+
}, void 0, fetchFn);
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { ProviderApiError, checkedFetch, getLeaseConnectionInfo, getProviderHealth, parseJsonResponse, uploadLeaseData, validateProviderUrl };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","names":[],"sources":["../../src/http/provider.ts"],"sourcesContent":["export class ProviderApiError extends Error {\n public readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = 'ProviderApiError';\n this.status = status;\n Object.setPrototypeOf(this, ProviderApiError.prototype);\n }\n}\n\nconst LOCALHOST_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);\n\nexport function validateProviderUrl(url: string): string {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw new ProviderApiError(0, `Invalid provider URL: ${url}`);\n }\n\n if (parsed.protocol === 'https:') {\n return url.replace(/\\/+$/, '');\n }\n\n if (parsed.protocol === 'http:' && LOCALHOST_HOSTS.has(parsed.hostname)) {\n return url.replace(/\\/+$/, '');\n }\n\n throw new ProviderApiError(\n 0,\n `Provider URL must use HTTPS (or HTTP for localhost): ${url}`,\n );\n}\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 30_000;\n\nexport async function checkedFetch(\n url: string,\n init?: RequestInit,\n timeoutMs: number = DEFAULT_FETCH_TIMEOUT_MS,\n fetchFn: typeof globalThis.fetch = globalThis.fetch,\n): Promise<Response> {\n const callerProvidedSignal = init?.signal != null;\n let controller: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n if (!callerProvidedSignal && timeoutMs > 0) {\n const ctrl = new AbortController();\n controller = ctrl;\n timer = setTimeout(() => ctrl.abort(), timeoutMs);\n init = { ...init, signal: ctrl.signal };\n }\n\n let res: Response;\n try {\n res = await fetchFn(url, init);\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n if (controller && !callerProvidedSignal) {\n throw new ProviderApiError(\n 0,\n `Request to ${url} timed out after ${timeoutMs}ms`,\n );\n }\n throw err;\n }\n throw new ProviderApiError(\n 0,\n `Network request to ${url} failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n if (!res.ok) {\n const body = await res\n .text()\n .catch(\n (readErr: unknown) =>\n `[body read failed: ${readErr instanceof Error ? readErr.message : String(readErr)}]`,\n );\n throw new ProviderApiError(res.status, body || `HTTP ${res.status}`);\n }\n return res;\n}\n\nexport async function parseJsonResponse<T>(\n res: Response,\n url: string,\n): Promise<T> {\n const text = await res.text();\n try {\n return JSON.parse(text) as T;\n } catch (parseErr) {\n const reason =\n parseErr instanceof Error ? parseErr.message : 'parse failed';\n throw new ProviderApiError(\n res.status,\n `Invalid JSON from ${url} (${reason}): ${text.slice(0, 200)}`,\n );\n }\n}\n\nexport interface ProviderHealthResponse {\n readonly status: string;\n readonly provider_uuid: string;\n readonly checks?: {\n readonly chain?: { readonly status: string };\n };\n}\n\nexport async function getProviderHealth(\n providerApiUrl: string,\n timeoutMs = 5_000,\n fetchFn?: typeof globalThis.fetch,\n): Promise<ProviderHealthResponse> {\n const validated = validateProviderUrl(providerApiUrl);\n const url = `${validated}/health`;\n const res = await checkedFetch(url, undefined, timeoutMs, fetchFn);\n return await parseJsonResponse<ProviderHealthResponse>(res, url);\n}\n\nexport interface InstanceInfo {\n readonly instance_index: number;\n readonly container_id: string;\n readonly image: string;\n readonly status: string;\n readonly ports?: Record<string, unknown>;\n readonly fqdn?: string;\n}\n\nexport interface ServiceConnectionDetails {\n readonly host?: string;\n readonly fqdn?: string;\n readonly ports?: Record<string, unknown>;\n readonly instances?: readonly InstanceInfo[];\n}\n\nexport interface ConnectionDetails {\n readonly host: string;\n readonly fqdn?: string;\n readonly ports?: Record<string, unknown>;\n readonly instances?: readonly InstanceInfo[];\n readonly protocol?: string;\n readonly metadata?: Record<string, string>;\n readonly services?: Record<string, ServiceConnectionDetails>;\n}\n\nexport interface LeaseConnectionResponse {\n readonly lease_uuid: string;\n readonly tenant: string;\n readonly provider_uuid: string;\n readonly connection: ConnectionDetails;\n}\n\nexport async function getLeaseConnectionInfo(\n providerApiUrl: string,\n leaseUuid: string,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<LeaseConnectionResponse> {\n const validated = validateProviderUrl(providerApiUrl);\n const url = `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/connection`;\n const res = await checkedFetch(\n url,\n {\n headers: { Authorization: `Bearer ${authToken}` },\n },\n undefined,\n fetchFn,\n );\n return await parseJsonResponse<LeaseConnectionResponse>(res, url);\n}\n\nexport async function uploadLeaseData(\n providerApiUrl: string,\n leaseUuid: string,\n payload: Uint8Array,\n authToken: string,\n fetchFn?: typeof globalThis.fetch,\n): Promise<void> {\n const validated = validateProviderUrl(providerApiUrl);\n await checkedFetch(\n `${validated}/v1/leases/${encodeURIComponent(leaseUuid)}/data`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/octet-stream',\n },\n body: payload,\n },\n undefined,\n fetchFn,\n );\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AuthTokenPayload, createAuthToken, createLeaseDataSignMessage, createSignMessage } from "./http/auth.js";
|
|
2
|
+
import { FredActionResponse, FredInstanceInfo, FredLeaseInfo, FredLeaseLogs, FredLeaseProvision, FredLeaseRelease, FredLeaseReleases, FredLeaseStatus, FredServiceStatus, MAX_TAIL, PollOptions, getLeaseInfo, getLeaseLogs, getLeaseProvision, getLeaseReleases, getLeaseStatus, pollLeaseUntilReady, restartLease, updateLease } from "./http/fred.js";
|
|
3
|
+
import { ConnectionDetails, InstanceInfo, LeaseConnectionResponse, ProviderApiError, ProviderHealthResponse, ServiceConnectionDetails, checkedFetch, getLeaseConnectionInfo, getProviderHealth, uploadLeaseData, validateProviderUrl } from "./http/provider.js";
|
|
4
|
+
import { BuildManifestOptions, buildManifest, buildStackManifest, deriveAppNameFromImage, getServiceNames, isStackManifest, mergeManifest, normalizePorts, parseStackManifest, validateServiceName } from "./manifest.js";
|
|
5
|
+
import { appStatus } from "./tools/appStatus.js";
|
|
6
|
+
import { browseCatalog, mapWithConcurrency } from "./tools/browseCatalog.js";
|
|
7
|
+
import { DeployAppInput, DeployAppResult, ServiceConfig, deployApp } from "./tools/deployApp.js";
|
|
8
|
+
import { fetchActiveLease } from "./tools/fetchActiveLease.js";
|
|
9
|
+
import { getAppLogs } from "./tools/getLogs.js";
|
|
10
|
+
import { resolveProviderUrl } from "./tools/resolveLeaseProvider.js";
|
|
11
|
+
import { restartApp } from "./tools/restartApp.js";
|
|
12
|
+
import { updateApp } from "./tools/updateApp.js";
|
|
13
|
+
import { CosmosClientManager, INFRASTRUCTURE_ERROR_CODES, ManifestMCPError, ManifestMCPErrorCode, ManifestMCPServerOptions, ManifestMCPServerOptions as ManifestMCPServerOptions$1, MnemonicServerConfig } from "@manifest-network/manifest-mcp-core";
|
|
14
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
15
|
+
|
|
16
|
+
//#region src/index.d.ts
|
|
17
|
+
declare class FredMCPServer {
|
|
18
|
+
private mcpServer;
|
|
19
|
+
private clientManager;
|
|
20
|
+
private walletProvider;
|
|
21
|
+
constructor(options: ManifestMCPServerOptions$1);
|
|
22
|
+
private requireSignArbitrary;
|
|
23
|
+
private getProviderAuthToken;
|
|
24
|
+
private getLeaseDataAuthToken;
|
|
25
|
+
private registerTools;
|
|
26
|
+
getServer(): Server;
|
|
27
|
+
getClientManager(): CosmosClientManager;
|
|
28
|
+
disconnect(): void;
|
|
29
|
+
}
|
|
30
|
+
declare function createMnemonicFredServer(config: MnemonicServerConfig): Promise<FredMCPServer>;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { type AuthTokenPayload, type BuildManifestOptions, type ConnectionDetails, type DeployAppInput, type DeployAppResult, type FredActionResponse, type FredInstanceInfo, type FredLeaseInfo, type FredLeaseLogs, type FredLeaseProvision, type FredLeaseRelease, type FredLeaseReleases, type FredLeaseStatus, FredMCPServer, type FredServiceStatus, INFRASTRUCTURE_ERROR_CODES, type InstanceInfo, type LeaseConnectionResponse, MAX_TAIL, ManifestMCPError, ManifestMCPErrorCode, type ManifestMCPServerOptions, type PollOptions, ProviderApiError, type ProviderHealthResponse, type ServiceConfig, type ServiceConnectionDetails, appStatus, browseCatalog, buildManifest, buildStackManifest, checkedFetch, createAuthToken, createLeaseDataSignMessage, createMnemonicFredServer, createSignMessage, deployApp, deriveAppNameFromImage, fetchActiveLease, getAppLogs, getLeaseConnectionInfo, getLeaseInfo, getLeaseLogs, getLeaseProvision, getLeaseReleases, getLeaseStatus, getProviderHealth, getServiceNames, isStackManifest, mapWithConcurrency, mergeManifest, normalizePorts, parseStackManifest, pollLeaseUntilReady, resolveProviderUrl, restartApp, restartLease, updateApp, updateLease, uploadLeaseData, validateProviderUrl, validateServiceName };
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;;cAwGa,aAAA;EAAA,QACH,SAAA;EAAA,QACA,aAAA;EAAA,QACA,cAAA;cAEI,OAAA,EAAS,0BAAA;EAAA,QAuBb,oBAAA;EAAA,QAUM,oBAAA;EAAA,QAiBA,qBAAA;EAAA,QAuBN,aAAA;EAoZR,SAAA,CAAA,GAAa,MAAA;EAIb,gBAAA,CAAA,GAAoB,mBAAA;EAIpB,UAAA,CAAA;AAAA;AAAA,iBAKc,wBAAA,CACd,MAAA,EAAQ,oBAAA,GACP,OAAA,CAAQ,aAAA"}
|