@nirmos/sdk 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/README.md +62 -0
- package/dist/cjs/client.js +61 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/core/errors.js +143 -0
- package/dist/cjs/core/errors.js.map +1 -0
- package/dist/cjs/core/metadata.js +104 -0
- package/dist/cjs/core/metadata.js.map +1 -0
- package/dist/cjs/core/transport.js +276 -0
- package/dist/cjs/core/transport.js.map +1 -0
- package/dist/cjs/core/types.js +3 -0
- package/dist/cjs/core/types.js.map +1 -0
- package/dist/cjs/gateway/chat-stream.js +262 -0
- package/dist/cjs/gateway/chat-stream.js.map +1 -0
- package/dist/cjs/gateway/chat.js +102 -0
- package/dist/cjs/gateway/chat.js.map +1 -0
- package/dist/cjs/gateway/embeddings.js +33 -0
- package/dist/cjs/gateway/embeddings.js.map +1 -0
- package/dist/cjs/gateway/gateway.js +18 -0
- package/dist/cjs/gateway/gateway.js.map +1 -0
- package/dist/cjs/gateway/images.js +36 -0
- package/dist/cjs/gateway/images.js.map +1 -0
- package/dist/cjs/gateway/mappers.js +184 -0
- package/dist/cjs/gateway/mappers.js.map +1 -0
- package/dist/cjs/gateway/types.js +3 -0
- package/dist/cjs/gateway/types.js.map +1 -0
- package/dist/cjs/index.js +25 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/prompts/cache.js +48 -0
- package/dist/cjs/prompts/cache.js.map +1 -0
- package/dist/cjs/prompts/mappers.js +242 -0
- package/dist/cjs/prompts/mappers.js.map +1 -0
- package/dist/cjs/prompts/prompts.js +121 -0
- package/dist/cjs/prompts/prompts.js.map +1 -0
- package/dist/cjs/prompts/render.js +86 -0
- package/dist/cjs/prompts/render.js.map +1 -0
- package/dist/cjs/prompts/types.js +3 -0
- package/dist/cjs/prompts/types.js.map +1 -0
- package/dist/cjs/prompts/versions.js +51 -0
- package/dist/cjs/prompts/versions.js.map +1 -0
- package/dist/esm/client.d.ts +28 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +58 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/core/errors.d.ts +72 -0
- package/dist/esm/core/errors.d.ts.map +1 -0
- package/dist/esm/core/errors.js +125 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/metadata.d.ts +11 -0
- package/dist/esm/core/metadata.d.ts.map +1 -0
- package/dist/esm/core/metadata.js +95 -0
- package/dist/esm/core/metadata.js.map +1 -0
- package/dist/esm/core/transport.d.ts +28 -0
- package/dist/esm/core/transport.d.ts.map +1 -0
- package/dist/esm/core/transport.js +272 -0
- package/dist/esm/core/transport.js.map +1 -0
- package/dist/esm/core/types.d.ts +43 -0
- package/dist/esm/core/types.d.ts.map +1 -0
- package/dist/esm/core/types.js +2 -0
- package/dist/esm/core/types.js.map +1 -0
- package/dist/esm/gateway/chat-stream.d.ts +9 -0
- package/dist/esm/gateway/chat-stream.d.ts.map +1 -0
- package/dist/esm/gateway/chat-stream.js +258 -0
- package/dist/esm/gateway/chat-stream.js.map +1 -0
- package/dist/esm/gateway/chat.d.ts +12 -0
- package/dist/esm/gateway/chat.d.ts.map +1 -0
- package/dist/esm/gateway/chat.js +98 -0
- package/dist/esm/gateway/chat.js.map +1 -0
- package/dist/esm/gateway/embeddings.d.ts +9 -0
- package/dist/esm/gateway/embeddings.d.ts.map +1 -0
- package/dist/esm/gateway/embeddings.js +29 -0
- package/dist/esm/gateway/embeddings.js.map +1 -0
- package/dist/esm/gateway/gateway.d.ts +12 -0
- package/dist/esm/gateway/gateway.d.ts.map +1 -0
- package/dist/esm/gateway/gateway.js +14 -0
- package/dist/esm/gateway/gateway.js.map +1 -0
- package/dist/esm/gateway/images.d.ts +9 -0
- package/dist/esm/gateway/images.d.ts.map +1 -0
- package/dist/esm/gateway/images.js +32 -0
- package/dist/esm/gateway/images.js.map +1 -0
- package/dist/esm/gateway/mappers.d.ts +11 -0
- package/dist/esm/gateway/mappers.d.ts.map +1 -0
- package/dist/esm/gateway/mappers.js +174 -0
- package/dist/esm/gateway/mappers.js.map +1 -0
- package/dist/esm/gateway/types.d.ts +168 -0
- package/dist/esm/gateway/types.d.ts.map +1 -0
- package/dist/esm/gateway/types.js +2 -0
- package/dist/esm/gateway/types.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/prompts/cache.d.ts +13 -0
- package/dist/esm/prompts/cache.d.ts.map +1 -0
- package/dist/esm/prompts/cache.js +44 -0
- package/dist/esm/prompts/cache.js.map +1 -0
- package/dist/esm/prompts/mappers.d.ts +8 -0
- package/dist/esm/prompts/mappers.d.ts.map +1 -0
- package/dist/esm/prompts/mappers.js +235 -0
- package/dist/esm/prompts/mappers.js.map +1 -0
- package/dist/esm/prompts/prompts.d.ts +17 -0
- package/dist/esm/prompts/prompts.d.ts.map +1 -0
- package/dist/esm/prompts/prompts.js +117 -0
- package/dist/esm/prompts/prompts.js.map +1 -0
- package/dist/esm/prompts/render.d.ts +3 -0
- package/dist/esm/prompts/render.d.ts.map +1 -0
- package/dist/esm/prompts/render.js +83 -0
- package/dist/esm/prompts/render.js.map +1 -0
- package/dist/esm/prompts/types.d.ts +119 -0
- package/dist/esm/prompts/types.d.ts.map +1 -0
- package/dist/esm/prompts/types.js +2 -0
- package/dist/esm/prompts/types.js.map +1 -0
- package/dist/esm/prompts/versions.d.ts +12 -0
- package/dist/esm/prompts/versions.d.ts.map +1 -0
- package/dist/esm/prompts/versions.js +47 -0
- package/dist/esm/prompts/versions.js.map +1 -0
- package/package.json +50 -0
- package/src/client.ts +89 -0
- package/src/core/errors.ts +160 -0
- package/src/core/metadata.ts +141 -0
- package/src/core/transport.ts +331 -0
- package/src/core/types.ts +51 -0
- package/src/gateway/chat-stream.ts +307 -0
- package/src/gateway/chat.ts +134 -0
- package/src/gateway/embeddings.ts +44 -0
- package/src/gateway/gateway.ts +17 -0
- package/src/gateway/images.ts +41 -0
- package/src/gateway/mappers.ts +234 -0
- package/src/gateway/types.ts +206 -0
- package/src/index.ts +83 -0
- package/src/prompts/cache.ts +50 -0
- package/src/prompts/mappers.ts +318 -0
- package/src/prompts/prompts.ts +188 -0
- package/src/prompts/render.ts +117 -0
- package/src/prompts/types.ts +148 -0
- package/src/prompts/versions.ts +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Nirmos TypeScript SDK
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for Nirmos Gateway and managed prompts. Supports Node.js 18+, ESM, CommonJS, streaming, normalized responses, stable error classes, and dependency-free prompt caching.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @nirmos/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Chat
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { Nirmos } from "@nirmos/sdk";
|
|
15
|
+
|
|
16
|
+
const nirmos = new Nirmos({
|
|
17
|
+
apiKey: process.env.NIRMOS_API_KEY!,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const response = await nirmos.gateway.chat.create({
|
|
21
|
+
model: "openai/gpt-4.1-mini",
|
|
22
|
+
messages: [{ role: "user", content: "Hello from Nirmos" }],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
console.log(response.outputText);
|
|
26
|
+
console.log(response.usage);
|
|
27
|
+
console.log(response.metadata.requestId);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Streaming
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
const stream = await nirmos.gateway.chat.stream({
|
|
34
|
+
model: "openai/gpt-4.1-mini",
|
|
35
|
+
messages: [{ role: "user", content: "Write a short announcement." }],
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
for await (const event of stream) {
|
|
39
|
+
if (event.type === "content.delta") {
|
|
40
|
+
process.stdout.write(event.delta ?? "");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const completion = await stream.finalResponse();
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Managed prompts
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
const response = await nirmos.gateway.chat.create({
|
|
51
|
+
model: "anthropic/claude-sonnet-4",
|
|
52
|
+
prompt: {
|
|
53
|
+
id: "support-reply",
|
|
54
|
+
variables: { customerName: "Asha", tone: "calm" },
|
|
55
|
+
},
|
|
56
|
+
messages: [{ role: "user", content: "My order has not arrived." }],
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Prompt retrieval uses a configurable in-memory TTL/LRU cache. Content changes create immutable versions; approved versions can be activated without application redeployment.
|
|
61
|
+
|
|
62
|
+
Full documentation lives in `apps/web/content/docs/sdk` in the Nirmos repository.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NirmosClient = exports.Nirmos = void 0;
|
|
4
|
+
const errors_js_1 = require("./core/errors.js");
|
|
5
|
+
const transport_js_1 = require("./core/transport.js");
|
|
6
|
+
const gateway_js_1 = require("./gateway/gateway.js");
|
|
7
|
+
const prompts_js_1 = require("./prompts/prompts.js");
|
|
8
|
+
class Nirmos {
|
|
9
|
+
gateway;
|
|
10
|
+
prompts;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
validateOptions(options);
|
|
13
|
+
const transport = new transport_js_1.HttpTransport({
|
|
14
|
+
apiKey: options.apiKey,
|
|
15
|
+
baseUrl: normalizeBaseUrl(options.baseUrl ?? "https://api.nirmos.com"),
|
|
16
|
+
timeoutMs: nonNegative(options.timeoutMs, 60_000),
|
|
17
|
+
maxRetries: nonNegativeInteger(options.maxRetries, 2),
|
|
18
|
+
fetch: options.fetch ?? globalThis.fetch,
|
|
19
|
+
headers: options.headers,
|
|
20
|
+
});
|
|
21
|
+
this.prompts = new prompts_js_1.Prompts(transport, options.promptCache);
|
|
22
|
+
this.gateway = new gateway_js_1.Gateway(transport, this.prompts);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.Nirmos = Nirmos;
|
|
26
|
+
exports.NirmosClient = Nirmos;
|
|
27
|
+
function validateOptions(options) {
|
|
28
|
+
if (!options || typeof options !== "object") {
|
|
29
|
+
throw configError("Nirmos options are required.");
|
|
30
|
+
}
|
|
31
|
+
if (!options.apiKey || !options.apiKey.trim()) {
|
|
32
|
+
throw configError("Nirmos apiKey is required.");
|
|
33
|
+
}
|
|
34
|
+
if (typeof (options.fetch ?? globalThis.fetch) !== "function") {
|
|
35
|
+
throw configError("No fetch implementation found. Provide options.fetch in this runtime.");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function normalizeBaseUrl(value) {
|
|
39
|
+
let url;
|
|
40
|
+
try {
|
|
41
|
+
url = new URL(value);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw configError("Nirmos baseUrl must be a valid absolute URL.");
|
|
45
|
+
}
|
|
46
|
+
return url.toString().replace(/\/+$/, "");
|
|
47
|
+
}
|
|
48
|
+
function nonNegative(value, fallback) {
|
|
49
|
+
return value !== undefined && Number.isFinite(value) && value >= 0
|
|
50
|
+
? value
|
|
51
|
+
: fallback;
|
|
52
|
+
}
|
|
53
|
+
function nonNegativeInteger(value, fallback) {
|
|
54
|
+
return value !== undefined && Number.isInteger(value) && value >= 0
|
|
55
|
+
? value
|
|
56
|
+
: fallback;
|
|
57
|
+
}
|
|
58
|
+
function configError(message) {
|
|
59
|
+
return new errors_js_1.ConfigurationError(message);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":";;;AAAA,gDAAsD;AACtD,sDAAoD;AAEpD,qDAA+C;AAC/C,qDAA+C;AAoB/C,MAAa,MAAM;IACR,OAAO,CAAU;IACjB,OAAO,CAAU;IAE1B,YAAY,OAAsB;QAChC,eAAe,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,4BAAa,CAAC;YAClC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC;YACtE,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;YACjD,UAAU,EAAE,kBAAkB,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;YACrD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;YACxC,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAO,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAO,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;CACF;AAlBD,wBAkBC;AAGkB,8BAAY;AAE/B,SAAS,eAAe,CAAC,OAAsB;IAC7C,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,WAAW,CAAC,8BAA8B,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9C,MAAM,WAAW,CAAC,4BAA4B,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,UAAU,EAAE,CAAC;QAC9D,MAAM,WAAW,CACf,uEAAuE,CACxE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,WAAW,CAAC,8CAA8C,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,WAAW,CAAC,KAAyB,EAAE,QAAgB;IAC9D,OAAO,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAChE,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,QAAQ,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CACzB,KAAyB,EACzB,QAAgB;IAEhB,OAAO,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QACjE,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,QAAQ,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,IAAI,8BAAkB,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PromptRenderError = exports.StreamError = exports.NetworkError = exports.RequestAbortedError = exports.TimeoutError = exports.ServerError = exports.RateLimitError = exports.ValidationError = exports.ConflictError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.APIError = exports.ConfigurationError = exports.NirmosError = void 0;
|
|
4
|
+
class NirmosError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
requestId;
|
|
7
|
+
traceId;
|
|
8
|
+
constructor(message, options = {}) {
|
|
9
|
+
super(message, { cause: options.cause });
|
|
10
|
+
this.name = "NirmosError";
|
|
11
|
+
this.code = options.code;
|
|
12
|
+
this.requestId = options.requestId;
|
|
13
|
+
this.traceId = options.traceId;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.NirmosError = NirmosError;
|
|
17
|
+
class ConfigurationError extends NirmosError {
|
|
18
|
+
constructor(message, options = {}) {
|
|
19
|
+
super(message, {
|
|
20
|
+
...options,
|
|
21
|
+
code: options.code ?? "SDK_CONFIGURATION_ERROR",
|
|
22
|
+
});
|
|
23
|
+
this.name = "ConfigurationError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.ConfigurationError = ConfigurationError;
|
|
27
|
+
class APIError extends NirmosError {
|
|
28
|
+
status;
|
|
29
|
+
retryable;
|
|
30
|
+
retryAfterMs;
|
|
31
|
+
details;
|
|
32
|
+
metadata;
|
|
33
|
+
headers;
|
|
34
|
+
constructor(message, options) {
|
|
35
|
+
super(message, options);
|
|
36
|
+
this.name = "APIError";
|
|
37
|
+
this.status = options.status;
|
|
38
|
+
this.retryable = options.retryable ?? false;
|
|
39
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
40
|
+
this.details = options.details;
|
|
41
|
+
this.metadata = options.metadata;
|
|
42
|
+
this.headers = options.headers;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.APIError = APIError;
|
|
46
|
+
class AuthenticationError extends APIError {
|
|
47
|
+
constructor(message, options) {
|
|
48
|
+
super(message, options);
|
|
49
|
+
this.name = "AuthenticationError";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.AuthenticationError = AuthenticationError;
|
|
53
|
+
class PermissionDeniedError extends APIError {
|
|
54
|
+
constructor(message, options) {
|
|
55
|
+
super(message, options);
|
|
56
|
+
this.name = "PermissionDeniedError";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.PermissionDeniedError = PermissionDeniedError;
|
|
60
|
+
class NotFoundError extends APIError {
|
|
61
|
+
constructor(message, options) {
|
|
62
|
+
super(message, options);
|
|
63
|
+
this.name = "NotFoundError";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.NotFoundError = NotFoundError;
|
|
67
|
+
class ConflictError extends APIError {
|
|
68
|
+
constructor(message, options) {
|
|
69
|
+
super(message, options);
|
|
70
|
+
this.name = "ConflictError";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.ConflictError = ConflictError;
|
|
74
|
+
class ValidationError extends APIError {
|
|
75
|
+
constructor(message, options) {
|
|
76
|
+
super(message, options);
|
|
77
|
+
this.name = "ValidationError";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.ValidationError = ValidationError;
|
|
81
|
+
class RateLimitError extends APIError {
|
|
82
|
+
constructor(message, options) {
|
|
83
|
+
super(message, options);
|
|
84
|
+
this.name = "RateLimitError";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.RateLimitError = RateLimitError;
|
|
88
|
+
class ServerError extends APIError {
|
|
89
|
+
constructor(message, options) {
|
|
90
|
+
super(message, options);
|
|
91
|
+
this.name = "ServerError";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.ServerError = ServerError;
|
|
95
|
+
class TimeoutError extends NirmosError {
|
|
96
|
+
timeoutMs;
|
|
97
|
+
constructor(timeoutMs, options = {}) {
|
|
98
|
+
super(`Request timed out after ${timeoutMs}ms.`, {
|
|
99
|
+
...options,
|
|
100
|
+
code: options.code ?? "REQUEST_TIMEOUT",
|
|
101
|
+
});
|
|
102
|
+
this.name = "TimeoutError";
|
|
103
|
+
this.timeoutMs = timeoutMs;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.TimeoutError = TimeoutError;
|
|
107
|
+
class RequestAbortedError extends NirmosError {
|
|
108
|
+
constructor(options = {}) {
|
|
109
|
+
super("Request was aborted.", {
|
|
110
|
+
...options,
|
|
111
|
+
code: options.code ?? "REQUEST_ABORTED",
|
|
112
|
+
});
|
|
113
|
+
this.name = "RequestAbortedError";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.RequestAbortedError = RequestAbortedError;
|
|
117
|
+
class NetworkError extends NirmosError {
|
|
118
|
+
constructor(cause) {
|
|
119
|
+
super("Unable to reach the Nirmos API.", {
|
|
120
|
+
cause,
|
|
121
|
+
code: "NETWORK_ERROR",
|
|
122
|
+
});
|
|
123
|
+
this.name = "NetworkError";
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.NetworkError = NetworkError;
|
|
127
|
+
class StreamError extends NirmosError {
|
|
128
|
+
constructor(message, options = {}) {
|
|
129
|
+
super(message, { ...options, code: options.code ?? "STREAM_ERROR" });
|
|
130
|
+
this.name = "StreamError";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.StreamError = StreamError;
|
|
134
|
+
class PromptRenderError extends NirmosError {
|
|
135
|
+
missingVariables;
|
|
136
|
+
constructor(message, missingVariables = []) {
|
|
137
|
+
super(message, { code: "PROMPT_RENDER_ERROR" });
|
|
138
|
+
this.name = "PromptRenderError";
|
|
139
|
+
this.missingVariables = missingVariables;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.PromptRenderError = PromptRenderError;
|
|
143
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractMetadata = extractMetadata;
|
|
4
|
+
exports.compactMetadata = compactMetadata;
|
|
5
|
+
exports.asUnknownRecord = asUnknownRecord;
|
|
6
|
+
exports.readString = readString;
|
|
7
|
+
exports.readNumber = readNumber;
|
|
8
|
+
exports.readBoolean = readBoolean;
|
|
9
|
+
exports.readArray = readArray;
|
|
10
|
+
function asRecord(value) {
|
|
11
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
12
|
+
? value
|
|
13
|
+
: undefined;
|
|
14
|
+
}
|
|
15
|
+
function stringValue(value) {
|
|
16
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
17
|
+
}
|
|
18
|
+
function numberValue(value) {
|
|
19
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
20
|
+
? value
|
|
21
|
+
: undefined;
|
|
22
|
+
}
|
|
23
|
+
function header(response, ...names) {
|
|
24
|
+
for (const name of names) {
|
|
25
|
+
const value = response.headers.get(name);
|
|
26
|
+
if (value)
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
function numericHeader(response, ...names) {
|
|
32
|
+
const value = header(response, ...names);
|
|
33
|
+
if (!value)
|
|
34
|
+
return undefined;
|
|
35
|
+
const number = Number.parseFloat(value.replace(/ms$/i, ""));
|
|
36
|
+
return Number.isFinite(number) ? number : undefined;
|
|
37
|
+
}
|
|
38
|
+
function extractMetadata(response, payload) {
|
|
39
|
+
const root = asRecord(payload);
|
|
40
|
+
const bodyMeta = asRecord(root?._meta) ?? asRecord(root?.meta) ?? asRecord(root?.metadata);
|
|
41
|
+
const metadata = {
|
|
42
|
+
requestId: stringValue(bodyMeta?.request_id) ??
|
|
43
|
+
stringValue(bodyMeta?.requestId) ??
|
|
44
|
+
header(response, "x-nirmos-request-id", "x-request-id"),
|
|
45
|
+
traceId: stringValue(bodyMeta?.trace_id) ??
|
|
46
|
+
stringValue(bodyMeta?.traceId) ??
|
|
47
|
+
header(response, "x-nirmos-trace-id", "x-trace-id"),
|
|
48
|
+
provider: stringValue(bodyMeta?.provider) ?? header(response, "x-nirmos-provider"),
|
|
49
|
+
model: stringValue(bodyMeta?.model) ?? header(response, "x-nirmos-model"),
|
|
50
|
+
latencyMs: numberValue(bodyMeta?.latency_ms) ??
|
|
51
|
+
numberValue(bodyMeta?.latencyMs) ??
|
|
52
|
+
numericHeader(response, "x-nirmos-response-time", "x-response-time"),
|
|
53
|
+
};
|
|
54
|
+
const cacheStatus = header(response, "x-nirmos-cache-status", "x-promptnetra-cache-status");
|
|
55
|
+
const cacheLayer = header(response, "x-nirmos-cache-layer", "x-promptnetra-cache-layer");
|
|
56
|
+
const remainingTtlSeconds = numericHeader(response, "x-nirmos-cache-remaining-ttl", "x-promptnetra-cache-remaining-ttl");
|
|
57
|
+
if (cacheStatus || cacheLayer || remainingTtlSeconds !== undefined) {
|
|
58
|
+
metadata.cache = {
|
|
59
|
+
status: cacheStatus,
|
|
60
|
+
layer: cacheLayer,
|
|
61
|
+
remainingTtlSeconds,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return metadata;
|
|
65
|
+
}
|
|
66
|
+
function compactMetadata(metadata) {
|
|
67
|
+
return Object.fromEntries(Object.entries(metadata).filter(([, value]) => value !== undefined));
|
|
68
|
+
}
|
|
69
|
+
function asUnknownRecord(value) {
|
|
70
|
+
return asRecord(value) ?? {};
|
|
71
|
+
}
|
|
72
|
+
function readString(record, ...keys) {
|
|
73
|
+
for (const key of keys) {
|
|
74
|
+
const value = stringValue(record[key]);
|
|
75
|
+
if (value !== undefined)
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
function readNumber(record, ...keys) {
|
|
81
|
+
for (const key of keys) {
|
|
82
|
+
const value = numberValue(record[key]);
|
|
83
|
+
if (value !== undefined)
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
function readBoolean(record, ...keys) {
|
|
89
|
+
for (const key of keys) {
|
|
90
|
+
const value = record[key];
|
|
91
|
+
if (typeof value === "boolean")
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
function readArray(record, ...keys) {
|
|
97
|
+
for (const key of keys) {
|
|
98
|
+
const value = record[key];
|
|
99
|
+
if (Array.isArray(value))
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/core/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpTransport = void 0;
|
|
4
|
+
const errors_js_1 = require("./errors.js");
|
|
5
|
+
const metadata_js_1 = require("./metadata.js");
|
|
6
|
+
const SDK_VERSION = "1.0.0";
|
|
7
|
+
class HttpTransport {
|
|
8
|
+
#config;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.#config = config;
|
|
11
|
+
}
|
|
12
|
+
async request(request) {
|
|
13
|
+
const response = await this.fetch(request);
|
|
14
|
+
const data = await parseResponseBody(response);
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
throw createApiError(response, data);
|
|
17
|
+
}
|
|
18
|
+
return { data: data, response };
|
|
19
|
+
}
|
|
20
|
+
async ensureSuccess(response) {
|
|
21
|
+
if (response.ok)
|
|
22
|
+
return response;
|
|
23
|
+
const data = await parseResponseBody(response);
|
|
24
|
+
throw createApiError(response, data);
|
|
25
|
+
}
|
|
26
|
+
async fetch(request) {
|
|
27
|
+
const maxRetries = request.options?.maxRetries ?? this.#config.maxRetries;
|
|
28
|
+
const retryableMethod = request.method === "GET" || request.options?.idempotencyKey !== undefined;
|
|
29
|
+
let attempt = 0;
|
|
30
|
+
while (true) {
|
|
31
|
+
try {
|
|
32
|
+
const response = await this.#fetchOnce(request);
|
|
33
|
+
if (retryableMethod &&
|
|
34
|
+
attempt < maxRetries &&
|
|
35
|
+
isRetryableStatus(response.status)) {
|
|
36
|
+
await response.body?.cancel();
|
|
37
|
+
await waitBeforeRetry(response, attempt, request.options?.signal);
|
|
38
|
+
attempt += 1;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
return response;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (retryableMethod &&
|
|
45
|
+
attempt < maxRetries &&
|
|
46
|
+
error instanceof errors_js_1.NetworkError) {
|
|
47
|
+
await wait(250 * 2 ** attempt, request.options?.signal);
|
|
48
|
+
attempt += 1;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async #fetchOnce(request) {
|
|
56
|
+
const timeoutMs = request.options?.timeoutMs ?? this.#config.timeoutMs;
|
|
57
|
+
const controller = new AbortController();
|
|
58
|
+
let timedOut = false;
|
|
59
|
+
let externallyAborted = false;
|
|
60
|
+
let timer;
|
|
61
|
+
let responseOwnsCleanup = false;
|
|
62
|
+
let cleanedUp = false;
|
|
63
|
+
const abortFromSignal = () => {
|
|
64
|
+
externallyAborted = true;
|
|
65
|
+
controller.abort(request.options?.signal?.reason);
|
|
66
|
+
cleanup();
|
|
67
|
+
};
|
|
68
|
+
const cleanup = () => {
|
|
69
|
+
if (cleanedUp)
|
|
70
|
+
return;
|
|
71
|
+
cleanedUp = true;
|
|
72
|
+
if (timer)
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
request.options?.signal?.removeEventListener("abort", abortFromSignal);
|
|
75
|
+
};
|
|
76
|
+
if (request.options?.signal?.aborted) {
|
|
77
|
+
throw new errors_js_1.RequestAbortedError({
|
|
78
|
+
cause: request.options.signal.reason,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
request.options?.signal?.addEventListener("abort", abortFromSignal, {
|
|
82
|
+
once: true,
|
|
83
|
+
});
|
|
84
|
+
if (timeoutMs > 0) {
|
|
85
|
+
timer = setTimeout(() => {
|
|
86
|
+
timedOut = true;
|
|
87
|
+
controller.abort();
|
|
88
|
+
cleanup();
|
|
89
|
+
}, timeoutMs);
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const response = await this.#config.fetch(this.#url(request), {
|
|
93
|
+
method: request.method,
|
|
94
|
+
headers: this.#headers(request),
|
|
95
|
+
body: request.body === undefined ? undefined : JSON.stringify(request.body),
|
|
96
|
+
signal: controller.signal,
|
|
97
|
+
});
|
|
98
|
+
if (!response.body)
|
|
99
|
+
return response;
|
|
100
|
+
responseOwnsCleanup = true;
|
|
101
|
+
const reader = response.body.getReader();
|
|
102
|
+
const body = new ReadableStream({
|
|
103
|
+
async pull(streamController) {
|
|
104
|
+
try {
|
|
105
|
+
const { done, value } = await reader.read();
|
|
106
|
+
if (done) {
|
|
107
|
+
cleanup();
|
|
108
|
+
streamController.close();
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
streamController.enqueue(value);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
cleanup();
|
|
116
|
+
if (timedOut) {
|
|
117
|
+
streamController.error(new errors_js_1.TimeoutError(timeoutMs, { cause: error }));
|
|
118
|
+
}
|
|
119
|
+
else if (externallyAborted || request.options?.signal?.aborted) {
|
|
120
|
+
streamController.error(new errors_js_1.RequestAbortedError({ cause: error }));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
streamController.error(new errors_js_1.NetworkError(error));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
async cancel(reason) {
|
|
128
|
+
try {
|
|
129
|
+
await reader.cancel(reason);
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
cleanup();
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
return new Response(body, {
|
|
137
|
+
headers: response.headers,
|
|
138
|
+
status: response.status,
|
|
139
|
+
statusText: response.statusText,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (timedOut)
|
|
144
|
+
throw new errors_js_1.TimeoutError(timeoutMs, { cause: error });
|
|
145
|
+
if (externallyAborted || request.options?.signal?.aborted) {
|
|
146
|
+
throw new errors_js_1.RequestAbortedError({ cause: error });
|
|
147
|
+
}
|
|
148
|
+
throw new errors_js_1.NetworkError(error);
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
if (!responseOwnsCleanup)
|
|
152
|
+
cleanup();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
#url(request) {
|
|
156
|
+
const url = new URL(request.path.replace(/^\//, ""), `${this.#config.baseUrl}/`);
|
|
157
|
+
for (const [key, value] of Object.entries(request.query ?? {})) {
|
|
158
|
+
if (value !== undefined)
|
|
159
|
+
url.searchParams.set(key, String(value));
|
|
160
|
+
}
|
|
161
|
+
return url.toString();
|
|
162
|
+
}
|
|
163
|
+
#headers(request) {
|
|
164
|
+
const headers = createHeaders(this.#config.headers);
|
|
165
|
+
headers.set("accept", "application/json");
|
|
166
|
+
headers.set("x-api-key", this.#config.apiKey);
|
|
167
|
+
headers.set("x-nirmos-sdk-version", SDK_VERSION);
|
|
168
|
+
if (request.body !== undefined) {
|
|
169
|
+
headers.set("content-type", "application/json");
|
|
170
|
+
}
|
|
171
|
+
createHeaders(request.options?.headers).forEach((value, key) => {
|
|
172
|
+
if (key.toLowerCase() !== "x-api-key")
|
|
173
|
+
headers.set(key, value);
|
|
174
|
+
});
|
|
175
|
+
if (request.options?.idempotencyKey) {
|
|
176
|
+
headers.set("idempotency-key", request.options.idempotencyKey);
|
|
177
|
+
}
|
|
178
|
+
return headers;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
exports.HttpTransport = HttpTransport;
|
|
182
|
+
async function parseResponseBody(response) {
|
|
183
|
+
if (response.status === 204)
|
|
184
|
+
return undefined;
|
|
185
|
+
const text = await response.text();
|
|
186
|
+
if (!text)
|
|
187
|
+
return undefined;
|
|
188
|
+
try {
|
|
189
|
+
return JSON.parse(text);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return text;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function createApiError(response, payload) {
|
|
196
|
+
const root = (0, metadata_js_1.asUnknownRecord)(payload);
|
|
197
|
+
const error = (0, metadata_js_1.asUnknownRecord)(root.error);
|
|
198
|
+
const metadata = (0, metadata_js_1.extractMetadata)(response, payload);
|
|
199
|
+
const message = ((0, metadata_js_1.readString)(error, "message") ??
|
|
200
|
+
(0, metadata_js_1.readString)(root, "message") ??
|
|
201
|
+
response.statusText) ||
|
|
202
|
+
"Nirmos API request failed.";
|
|
203
|
+
const code = (0, metadata_js_1.readString)(error, "code", "type") ?? (0, metadata_js_1.readString)(root, "code");
|
|
204
|
+
const retryable = (0, metadata_js_1.readBoolean)(error, "retryable") ?? isRetryableStatus(response.status);
|
|
205
|
+
const retryAfterMs = parseRetryAfter(response.headers.get("retry-after"));
|
|
206
|
+
const options = {
|
|
207
|
+
status: response.status,
|
|
208
|
+
code,
|
|
209
|
+
retryable,
|
|
210
|
+
retryAfterMs,
|
|
211
|
+
details: error.details,
|
|
212
|
+
metadata,
|
|
213
|
+
requestId: metadata.requestId,
|
|
214
|
+
traceId: metadata.traceId,
|
|
215
|
+
headers: response.headers,
|
|
216
|
+
};
|
|
217
|
+
if (response.status === 401)
|
|
218
|
+
return new errors_js_1.AuthenticationError(message, options);
|
|
219
|
+
if (response.status === 403)
|
|
220
|
+
return new errors_js_1.PermissionDeniedError(message, options);
|
|
221
|
+
if (response.status === 404)
|
|
222
|
+
return new errors_js_1.NotFoundError(message, options);
|
|
223
|
+
if (response.status === 409)
|
|
224
|
+
return new errors_js_1.ConflictError(message, options);
|
|
225
|
+
if (response.status === 422 || response.status === 400) {
|
|
226
|
+
return new errors_js_1.ValidationError(message, options);
|
|
227
|
+
}
|
|
228
|
+
if (response.status === 429)
|
|
229
|
+
return new errors_js_1.RateLimitError(message, options);
|
|
230
|
+
if (response.status >= 500)
|
|
231
|
+
return new errors_js_1.ServerError(message, options);
|
|
232
|
+
return new errors_js_1.APIError(message, options);
|
|
233
|
+
}
|
|
234
|
+
function isRetryableStatus(status) {
|
|
235
|
+
return status === 408 || status === 429 || status >= 500;
|
|
236
|
+
}
|
|
237
|
+
function parseRetryAfter(value) {
|
|
238
|
+
if (!value)
|
|
239
|
+
return undefined;
|
|
240
|
+
const seconds = Number(value);
|
|
241
|
+
if (Number.isFinite(seconds))
|
|
242
|
+
return Math.max(0, seconds * 1_000);
|
|
243
|
+
const date = Date.parse(value);
|
|
244
|
+
return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());
|
|
245
|
+
}
|
|
246
|
+
async function waitBeforeRetry(response, attempt, signal) {
|
|
247
|
+
const retryAfter = parseRetryAfter(response.headers.get("retry-after"));
|
|
248
|
+
await wait(retryAfter ?? 250 * 2 ** attempt, signal);
|
|
249
|
+
}
|
|
250
|
+
async function wait(milliseconds, signal) {
|
|
251
|
+
if (signal?.aborted) {
|
|
252
|
+
throw new errors_js_1.RequestAbortedError({ cause: signal.reason });
|
|
253
|
+
}
|
|
254
|
+
await new Promise((resolve, reject) => {
|
|
255
|
+
const finish = () => {
|
|
256
|
+
signal?.removeEventListener("abort", abort);
|
|
257
|
+
resolve();
|
|
258
|
+
};
|
|
259
|
+
const timer = setTimeout(finish, milliseconds);
|
|
260
|
+
const abort = () => {
|
|
261
|
+
clearTimeout(timer);
|
|
262
|
+
signal?.removeEventListener("abort", abort);
|
|
263
|
+
reject(new errors_js_1.RequestAbortedError({ cause: signal?.reason }));
|
|
264
|
+
};
|
|
265
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function createHeaders(input) {
|
|
269
|
+
if (!input)
|
|
270
|
+
return new Headers();
|
|
271
|
+
if (Array.isArray(input)) {
|
|
272
|
+
return new Headers(input.map(([key, value]) => [key, value]));
|
|
273
|
+
}
|
|
274
|
+
return new Headers(input);
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=transport.js.map
|