@openstatus/health-openai 0.1.4-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @openstatus/health-openai
2
+
3
+ [OpenAI](https://openai.com/) probe for
4
+ [`@openstatus/health`](https://jsr.io/@openstatus/health). Sends
5
+ `GET {baseUrl}/v1/models` with your API key as a bearer header, so it proves
6
+ both that the API answers and that the key is valid — with `fetch` alone, on
7
+ every runtime, and without spending a single token.
8
+
9
+ ```sh
10
+ deno add jsr:@openstatus/health jsr:@openstatus/health-openai
11
+ npm install @openstatus/health @openstatus/health-openai
12
+ ```
13
+
14
+ ```ts
15
+ import { createHealthHandler, readEnv } from "@openstatus/health";
16
+ import { openaiProbe } from "@openstatus/health-openai";
17
+
18
+ const apiKey = readEnv("OPENAI_API_KEY");
19
+
20
+ Deno.serve(
21
+ createHealthHandler({
22
+ probes: [
23
+ // the factory validates `apiKey` at construction, so pass a
24
+ // placeholder and let `skip` keep the unconfigured check from running.
25
+ openaiProbe({
26
+ apiKey: apiKey || "unconfigured",
27
+ skip: () => !apiKey,
28
+ }),
29
+ ],
30
+ }),
31
+ );
32
+ ```
33
+
34
+ `apiKey` is the `sk-…` key from the OpenAI dashboard; a project key with the
35
+ `Models` read permission is enough. Listing models is a free read with no side
36
+ effects and no rate-limit cost worth mentioning, so the probe can run on every
37
+ health request. `baseUrl` defaults to `https://api.openai.com` and takes the
38
+ origin of any OpenAI-compatible server — Azure OpenAI, a gateway or a local
39
+ model server — as long as it serves `/v1/models`. Like every probe here, this
40
+ one never reads the environment itself — pass the values in, and use `skip`
41
+ for environments where OpenAI is not configured.
42
+
43
+ A 2xx here means the API is up and the key authenticates. It does not prove
44
+ that a specific model is available or that completions are within their rate
45
+ limit; a model-level outage shows up in your request errors before it shows up
46
+ here.
47
+
48
+ ```ts
49
+ openaiProbe({
50
+ apiKey: apiKey || "unconfigured",
51
+ // optional overrides from the Probe contract
52
+ name: "llm",
53
+ critical: true,
54
+ timeoutMs: 2000,
55
+ skip: () => !apiKey,
56
+ });
57
+ ```
58
+
59
+ Non-critical by default: most services can answer without a model call, so an
60
+ outage degrades the report instead of taking the service out of rotation. Set
61
+ `critical: true` for a service whose every request is an inference.
62
+
63
+ ## About openstatus
64
+
65
+ [openstatus](https://www.openstatus.dev/) is the open-source uptime monitoring
66
+ and status page platform. This package is part of
67
+ [`@openstatus/health`](https://github.com/openstatusHQ/health), the `/health`
68
+ endpoints behind openstatus's own services, extracted so any JavaScript server
69
+ can expose one. Point an
70
+ [openstatus monitor](https://www.openstatus.dev/docs/reference/http-monitor)
71
+ at the endpoint and assert on `status` in the body to be alerted on
72
+ `degraded` before it becomes `unhealthy`.
73
+
74
+ Source: [github.com/openstatusHQ/health](https://github.com/openstatusHQ/health).
75
+ Issues and PRs welcome.
76
+
77
+ ## License
78
+
79
+ [MIT](https://github.com/openstatusHQ/health/blob/main/LICENSE)
@@ -0,0 +1,30 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+
25
+ Object.defineProperty(exports, '__toESM', {
26
+ enumerable: true,
27
+ get: function () {
28
+ return __toESM;
29
+ }
30
+ });
package/dist/mod.cjs ADDED
@@ -0,0 +1,36 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const __openstatus_health = require_rolldown_runtime.__toESM(require("@openstatus/health"));
3
+
4
+ //#region src/mod.ts
5
+ /** API base URL when `baseUrl` is unset. */
6
+ const openaiDefaultBaseUrl = "https://api.openai.com";
7
+ /** Probe name when `name` is unset. */
8
+ const openaiDefaultName = "openai";
9
+ /** A probe that expects 2xx from `GET {baseUrl}/v1/models` with `apiKey` as a bearer token; non-critical by default. Throws `ProbeConfigError` for an empty `apiKey` or an invalid `baseUrl`. */
10
+ function openaiProbe(options) {
11
+ const doFetch = options.fetch ?? globalThis.fetch;
12
+ const url = (0, __openstatus_health.probeUrl)({
13
+ probe: "openaiProbe",
14
+ field: "baseUrl",
15
+ value: options.baseUrl ?? openaiDefaultBaseUrl,
16
+ path: "/v1/models"
17
+ });
18
+ if (typeof options.apiKey !== "string" || options.apiKey.length === 0) throw new __openstatus_health.ProbeConfigError("openaiProbe", "apiKey", typeof options.apiKey !== "string" ? `must be a string, got ${String(options.apiKey)}` : "must not be empty");
19
+ const headers = { authorization: `Bearer ${options.apiKey}` };
20
+ return {
21
+ name: options.name ?? openaiDefaultName,
22
+ critical: options.critical ?? false,
23
+ timeoutMs: options.timeoutMs,
24
+ skip: options.skip,
25
+ run: (signal) => (0, __openstatus_health.expectOk)(doFetch(url, {
26
+ method: "GET",
27
+ headers,
28
+ signal
29
+ }))
30
+ };
31
+ }
32
+
33
+ //#endregion
34
+ exports.openaiDefaultBaseUrl = openaiDefaultBaseUrl;
35
+ exports.openaiDefaultName = openaiDefaultName;
36
+ exports.openaiProbe = openaiProbe;
package/dist/mod.d.cts ADDED
@@ -0,0 +1,23 @@
1
+ import { Probe, ProbeOverrides } from "@openstatus/health";
2
+
3
+ //#region src/mod.d.ts
4
+
5
+ /** API base URL when `baseUrl` is unset. */
6
+ declare const openaiDefaultBaseUrl = "https://api.openai.com";
7
+ /** Probe name when `name` is unset. */
8
+ declare const openaiDefaultName = "openai";
9
+ /** Options for `openaiProbe()`. */
10
+ interface OpenaiProbeOptions extends ProbeOverrides {
11
+ /** An OpenAI API key (`sk-…`). */
12
+ readonly apiKey: string;
13
+ /** API host. Default `openaiDefaultBaseUrl`. */
14
+ readonly baseUrl?: string | URL;
15
+ /** Replacement `fetch`, for tests. */
16
+ readonly fetch?: typeof fetch;
17
+ }
18
+ /** A probe that expects 2xx from `GET {baseUrl}/v1/models` with `apiKey` as a bearer token; non-critical by default. Throws `ProbeConfigError` for an empty `apiKey` or an invalid `baseUrl`. */
19
+ declare function openaiProbe(options: OpenaiProbeOptions): Probe;
20
+ //# sourceMappingURL=mod.d.ts.map
21
+ //#endregion
22
+ export { OpenaiProbeOptions, openaiDefaultBaseUrl, openaiDefaultName, openaiProbe };
23
+ //# sourceMappingURL=mod.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.cts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AAoCqC,cAfxB,oBAAA,GAewB,wBAAA;;AAA0B,cAblD,iBAAA,GAakD,QAAA;;UAV9C,kBAAA,SAA2B;;;;8BAId;;0BAEJ;;;iBAIV,WAAA,UAAqB,qBAAqB"}
package/dist/mod.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { Probe, ProbeOverrides } from "@openstatus/health";
2
+
3
+ //#region src/mod.d.ts
4
+
5
+ /** API base URL when `baseUrl` is unset. */
6
+ declare const openaiDefaultBaseUrl = "https://api.openai.com";
7
+ /** Probe name when `name` is unset. */
8
+ declare const openaiDefaultName = "openai";
9
+ /** Options for `openaiProbe()`. */
10
+ interface OpenaiProbeOptions extends ProbeOverrides {
11
+ /** An OpenAI API key (`sk-…`). */
12
+ readonly apiKey: string;
13
+ /** API host. Default `openaiDefaultBaseUrl`. */
14
+ readonly baseUrl?: string | URL;
15
+ /** Replacement `fetch`, for tests. */
16
+ readonly fetch?: typeof fetch;
17
+ }
18
+ /** A probe that expects 2xx from `GET {baseUrl}/v1/models` with `apiKey` as a bearer token; non-critical by default. Throws `ProbeConfigError` for an empty `apiKey` or an invalid `baseUrl`. */
19
+ declare function openaiProbe(options: OpenaiProbeOptions): Probe;
20
+ //# sourceMappingURL=mod.d.ts.map
21
+ //#endregion
22
+ export { OpenaiProbeOptions, openaiDefaultBaseUrl, openaiDefaultName, openaiProbe };
23
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AAoCqC,cAfxB,oBAAA,GAewB,wBAAA;;AAA0B,cAblD,iBAAA,GAakD,QAAA;;UAV9C,kBAAA,SAA2B;;;;8BAId;;0BAEJ;;;iBAIV,WAAA,UAAqB,qBAAqB"}
package/dist/mod.js ADDED
@@ -0,0 +1,34 @@
1
+ import { ProbeConfigError, expectOk, probeUrl } from "@openstatus/health";
2
+
3
+ //#region src/mod.ts
4
+ /** API base URL when `baseUrl` is unset. */
5
+ const openaiDefaultBaseUrl = "https://api.openai.com";
6
+ /** Probe name when `name` is unset. */
7
+ const openaiDefaultName = "openai";
8
+ /** A probe that expects 2xx from `GET {baseUrl}/v1/models` with `apiKey` as a bearer token; non-critical by default. Throws `ProbeConfigError` for an empty `apiKey` or an invalid `baseUrl`. */
9
+ function openaiProbe(options) {
10
+ const doFetch = options.fetch ?? globalThis.fetch;
11
+ const url = probeUrl({
12
+ probe: "openaiProbe",
13
+ field: "baseUrl",
14
+ value: options.baseUrl ?? openaiDefaultBaseUrl,
15
+ path: "/v1/models"
16
+ });
17
+ if (typeof options.apiKey !== "string" || options.apiKey.length === 0) throw new ProbeConfigError("openaiProbe", "apiKey", typeof options.apiKey !== "string" ? `must be a string, got ${String(options.apiKey)}` : "must not be empty");
18
+ const headers = { authorization: `Bearer ${options.apiKey}` };
19
+ return {
20
+ name: options.name ?? openaiDefaultName,
21
+ critical: options.critical ?? false,
22
+ timeoutMs: options.timeoutMs,
23
+ skip: options.skip,
24
+ run: (signal) => expectOk(doFetch(url, {
25
+ method: "GET",
26
+ headers,
27
+ signal
28
+ }))
29
+ };
30
+ }
31
+
32
+ //#endregion
33
+ export { openaiDefaultBaseUrl, openaiDefaultName, openaiProbe };
34
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","names":["options: OpenaiProbeOptions"],"sources":["../src/mod.ts"],"sourcesContent":["/**\n * OpenAI reachability probe for `@openstatus/health`, against `/v1/models`.\n *\n * ```ts\n * import { openaiProbe } from \"@openstatus/health-openai\";\n *\n * const probe = openaiProbe({ apiKey: env.OPENAI_API_KEY });\n * ```\n *\n * @module\n */\n\nimport {\n expectOk,\n type Probe,\n ProbeConfigError,\n type ProbeOverrides,\n probeUrl,\n} from \"@openstatus/health\";\n\n/** API base URL when `baseUrl` is unset. */\nexport const openaiDefaultBaseUrl = \"https://api.openai.com\";\n/** Probe name when `name` is unset. */\nexport const openaiDefaultName = \"openai\";\n\n/** Options for `openaiProbe()`. */\nexport interface OpenaiProbeOptions extends ProbeOverrides {\n /** An OpenAI API key (`sk-…`). */\n readonly apiKey: string;\n /** API host. Default `openaiDefaultBaseUrl`. */\n readonly baseUrl?: string | URL;\n /** Replacement `fetch`, for tests. */\n readonly fetch?: typeof fetch;\n}\n\n/** A probe that expects 2xx from `GET {baseUrl}/v1/models` with `apiKey` as a bearer token; non-critical by default. Throws `ProbeConfigError` for an empty `apiKey` or an invalid `baseUrl`. */\nexport function openaiProbe(options: OpenaiProbeOptions): Probe {\n const doFetch = options.fetch ?? globalThis.fetch;\n const url = probeUrl({\n probe: \"openaiProbe\",\n field: \"baseUrl\",\n value: options.baseUrl ?? openaiDefaultBaseUrl,\n path: \"/v1/models\",\n });\n if (typeof options.apiKey !== \"string\" || options.apiKey.length === 0) {\n throw new ProbeConfigError(\n \"openaiProbe\",\n \"apiKey\",\n typeof options.apiKey !== \"string\"\n ? `must be a string, got ${String(options.apiKey)}`\n : \"must not be empty\",\n );\n }\n const headers = { authorization: `Bearer ${options.apiKey}` };\n return {\n name: options.name ?? openaiDefaultName,\n critical: options.critical ?? false,\n timeoutMs: options.timeoutMs,\n skip: options.skip,\n run: (signal) => expectOk(doFetch(url, { method: \"GET\", headers, signal })),\n };\n}\n"],"mappings":";;;;AAqBA,MAAa,uBAAuB;;AAEpC,MAAa,oBAAoB;;AAajC,SAAgB,YAAYA,SAAoC;CAC9D,MAAM,UAAU,QAAQ,SAAS,WAAW;CAC5C,MAAM,MAAM,SAAS;EACnB,OAAO;EACP,OAAO;EACP,OAAO,QAAQ,WAAW;EAC1B,MAAM;CACP,EAAC;AACF,YAAW,QAAQ,WAAW,YAAY,QAAQ,OAAO,WAAW,EAClE,OAAM,IAAI,iBACR,eACA,iBACO,QAAQ,WAAW,YACrB,wBAAwB,OAAO,QAAQ,OAAO,CAAC,IAChD;CAGR,MAAM,UAAU,EAAE,gBAAgB,SAAS,QAAQ,OAAO,EAAG;AAC7D,QAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,UAAU,QAAQ,YAAY;EAC9B,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd,KAAK,CAAC,WAAW,SAAS,QAAQ,KAAK;GAAE,QAAQ;GAAO;GAAS;EAAQ,EAAC,CAAC;CAC5E;AACF"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@openstatus/health-openai",
3
+ "version": "0.1.4-dev.0",
4
+ "description": "OpenAI API probe for @openstatus/health",
5
+ "keywords": [
6
+ "openstatus",
7
+ "health",
8
+ "healthcheck",
9
+ "openai",
10
+ "llm",
11
+ "ai"
12
+ ],
13
+ "license": "MIT",
14
+ "author": {
15
+ "name": "openstatus",
16
+ "url": "https://www.openstatus.dev/"
17
+ },
18
+ "homepage": "https://github.com/openstatusHQ/health",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/openstatusHQ/health.git",
22
+ "directory": "packages/openai/"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/openstatusHQ/health/issues"
26
+ },
27
+ "type": "module",
28
+ "module": "./dist/mod.js",
29
+ "main": "./dist/mod.cjs",
30
+ "types": "./dist/mod.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": {
34
+ "import": "./dist/mod.d.ts",
35
+ "require": "./dist/mod.d.cts"
36
+ },
37
+ "import": "./dist/mod.js",
38
+ "require": "./dist/mod.cjs"
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "sideEffects": false,
43
+ "files": [
44
+ "dist/"
45
+ ],
46
+ "engines": {
47
+ "node": ">=22"
48
+ },
49
+ "peerDependencies": {
50
+ "@openstatus/health": "^0.1.4-dev.0"
51
+ },
52
+ "devDependencies": {
53
+ "tsdown": "^0.12.7",
54
+ "typescript": "^5.8.3"
55
+ },
56
+ "scripts": {
57
+ "build": "tsdown",
58
+ "prepack": "tsdown",
59
+ "test": "node --experimental-transform-types --test"
60
+ }
61
+ }