ainvoker 1.0.2 → 3.0.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 CHANGED
@@ -2,33 +2,39 @@
2
2
 
3
3
  Official TypeScript/JavaScript SDK for the AInvoker AI gateway.
4
4
 
5
+ [Docs](https://ainvoker.com/docs/sdk) · [Getting started](https://ainvoker.com/docs/getting-started) · [API](https://ainvoker-api.onrender.com)
6
+
7
+ AInvoker is an AI gateway. This package calls one HTTP API and routes to providers such as OpenAI and Gemini. Create projects, API keys, and billing in the [dashboard](https://ainvoker.com). Use the SDK to call models from your application.
8
+
9
+ Current release: **2.0.0** (`ai.text.chat` for `POST /v1/text/chat`).
10
+
5
11
  ## Install
6
12
 
7
13
  ```bash
8
14
  npm install ainvoker
9
15
  ```
10
16
 
11
- Requires Node.js 18+ (native `fetch`).
17
+ Requires Node.js 18+ (native `fetch`). The package ships ESM and CommonJS.
12
18
 
13
19
  ## Quick start
14
20
 
15
21
  ```ts
16
- import { Ainvoker, isAinvokerError } from "ainvoker"
22
+ import { AInvoker, isAInvokerError } from "ainvoker"
17
23
 
18
- const ai = new Ainvoker({
24
+ const ai = new AInvoker({
19
25
  apiKey: process.env.AINVOKER_API_KEY!,
20
- // optional — defaults to http://localhost:3000
21
- // baseUrl: "https://api.example.com",
26
+ // optional — defaults to https://ainvoker-api.onrender.com
22
27
  })
23
28
 
24
29
  try {
25
30
  const result = await ai.text.chat({
26
- model: "openai/gpt-4o-mini",
31
+ provider: "openai",
32
+ model: "gpt-4o-mini",
27
33
  messages: [{ role: "user", content: "Hello" }],
28
34
  })
29
35
  console.log(result.message.content)
30
36
  } catch (error) {
31
- if (isAinvokerError(error)) {
37
+ if (isAInvokerError(error)) {
32
38
  console.error(error.status, error.code, error.message)
33
39
  } else {
34
40
  throw error
@@ -36,34 +42,72 @@ try {
36
42
  }
37
43
  ```
38
44
 
39
- ## Local smoke
45
+ 1. [Sign up](https://ainvoker.com/signup) and open your Personal workspace.
46
+ 2. Create a project and an API key (`ain_…`). Keep it server-side.
47
+ 3. Call `ai.text.chat`. See [Getting Started](https://ainvoker.com/docs/getting-started).
40
48
 
41
- With the API running locally:
49
+ ## Client options
42
50
 
43
- 1. Copy `.env.example` → `.env` and set `AINVOKER_API_KEY`
44
- 2. Run:
51
+ | Option | Required | Notes |
52
+ | --- | --- | --- |
53
+ | `apiKey` | Yes | Project key starting with `ain_`. Sent as `Authorization: Bearer`. |
54
+ | `baseUrl` | No | Defaults to `https://ainvoker-api.onrender.com`. |
45
55
 
46
- ```bash
47
- npm run smoke
48
- ```
56
+ ## Text chat
49
57
 
50
- Optional env: `AINVOKER_BASE_URL`, `AINVOKER_MODEL`.
58
+ `ai.text.chat(params)` calls `POST /v1/text/chat` and unwraps the `{ data }` envelope.
51
59
 
52
- ## Development
60
+ | Field | Required | Notes |
61
+ | --- | --- | --- |
62
+ | `provider` | No | Catalog provider, for example `openai` or `gemini`. When set, autocomplete narrows `model` to that provider. When a `model` is chosen first, autocomplete narrows `provider` to matching providers. |
63
+ | `model` | Yes | Short model name (for example `gpt-4o-mini`). With `provider`, the SDK sends `provider/model`. Without `provider`, the bare name is sent and the API resolves it when unique. |
64
+ | `messages` | Yes | At least one message. Roles: `system`, `user`, `assistant`. |
65
+ | `temperature` | No | Sampling temperature from 0 to 2. |
66
+ | `maxTokens` | No | Maximum tokens to generate. When omitted, the gateway reserves and caps output at 8192. |
53
67
 
54
- ```bash
55
- npm install
56
- npm test
57
- npm run build
58
- ```
68
+ The result is `{ id, model, message, usage }`. `usage` is `{ inputTokens, outputTokens, totalTokens }` or `null` when the gateway does not report it.
69
+
70
+ For Gemini models, include at least one `user` or `assistant` message. A system-only prompt is not enough. Streaming is not available.
71
+
72
+ Model catalog and plan limits: [Models](https://ainvoker.com/docs/models) · [Limits](https://ainvoker.com/docs/limits).
73
+
74
+ ## Errors
59
75
 
60
- ## Publishing
76
+ Failures throw `AInvokerError` (`status`, `code`, `message`, and `body` when the response was parsed). Use `isAInvokerError` to narrow the type.
61
77
 
62
- Version is semver (`0.1.0` while the API surface is early). Before publish:
78
+ | HTTP | Code | Typical cause |
79
+ | --- | --- | --- |
80
+ | 400 | `VALIDATION_ERROR` | Invalid request body |
81
+ | 401 | `UNAUTHORIZED` | Missing, invalid, or expired API key |
82
+ | 402 | `SUBSCRIPTION_REQUIRED` | No active plan on the workspace |
83
+ | 403 | `FORBIDDEN` | Access denied for this project |
84
+ | 403 | `MODEL_NOT_ALLOWED_ON_PLAN` | Model not available on your plan |
85
+ | 403 | `MODEL_DISABLED` | Model disabled on the project allowlist |
86
+ | 404 | `NOT_FOUND` | Unknown model |
87
+ | 429 | `RATE_LIMIT_EXCEEDED` | Monthly request or token quota |
88
+ | 500 | `INTERNAL_ERROR` | Unexpected server error |
89
+ | 502 | `UPSTREAM_ERROR` | Upstream provider failed |
90
+
91
+ Client-side codes (no HTTP success body): `NETWORK_ERROR`, `INVALID_RESPONSE`, `HTTP_ERROR`.
92
+
93
+ See [Errors](https://ainvoker.com/docs/errors).
94
+
95
+ ## Browser
96
+
97
+ Do not put `ain_` keys in frontend code. The supported pattern is: the browser calls your backend, and your server uses this SDK with `AINVOKER_API_KEY`.
98
+
99
+ Direct browser calls also need the app origin under **Project → Settings → Allowed app URLs** (exact scheme, host, and port). Node and other server calls have no `Origin` header and do not need an entry. Origin allowlisting does not hide a key shipped in a bundle.
100
+
101
+ See [Browser usage](https://ainvoker.com/docs/sdk/browser).
102
+
103
+ ## Local smoke
63
104
 
64
105
  ```bash
65
- npm run prepublishOnly # typecheck + test + build
66
- npm publish # requires npm login + @ainvoker org access
106
+ AINVOKER_API_KEY=ain_... npm run smoke
67
107
  ```
68
108
 
69
- `publishConfig.access` is `public` so the scoped package can be published without a paid org private default.
109
+ Optional: `AINVOKER_BASE_URL`, `AINVOKER_MODEL` (defaults to `openai/gpt-4o-mini` as a slug; omit `provider` in smoke and send the env value as `model`).
110
+
111
+ ## License
112
+
113
+ MIT
package/dist/index.cjs CHANGED
@@ -1,21 +1,21 @@
1
1
  'use strict';
2
2
 
3
3
  // src/errors.ts
4
- var AinvokerError = class extends Error {
4
+ var AInvokerError = class extends Error {
5
5
  status;
6
6
  code;
7
7
  /** Parsed response body when available (error envelope or raw JSON). */
8
8
  body;
9
9
  constructor(status, code, message, body = void 0) {
10
10
  super(message);
11
- this.name = "AinvokerError";
11
+ this.name = "AInvokerError";
12
12
  this.status = status;
13
13
  this.code = code;
14
14
  this.body = body;
15
15
  }
16
16
  };
17
- function isAinvokerError(error) {
18
- return error instanceof AinvokerError;
17
+ function isAInvokerError(error) {
18
+ return error instanceof AInvokerError;
19
19
  }
20
20
 
21
21
  // src/http.ts
@@ -60,7 +60,7 @@ var HttpClient = class {
60
60
  });
61
61
  } catch (cause) {
62
62
  const message = cause instanceof Error ? cause.message : "Network request failed";
63
- throw new AinvokerError(0, "NETWORK_ERROR", message);
63
+ throw new AInvokerError(0, "NETWORK_ERROR", message);
64
64
  }
65
65
  const text = await response.text();
66
66
  let json = void 0;
@@ -68,7 +68,7 @@ var HttpClient = class {
68
68
  try {
69
69
  json = JSON.parse(text);
70
70
  } catch {
71
- throw new AinvokerError(
71
+ throw new AInvokerError(
72
72
  response.status,
73
73
  "INVALID_RESPONSE",
74
74
  "Response body was not valid JSON",
@@ -78,7 +78,7 @@ var HttpClient = class {
78
78
  }
79
79
  if (!response.ok) {
80
80
  const parsed = parseErrorPayload(json);
81
- throw new AinvokerError(
81
+ throw new AInvokerError(
82
82
  response.status,
83
83
  parsed?.code ?? "HTTP_ERROR",
84
84
  parsed?.message ?? `Request failed with status ${response.status}`,
@@ -86,7 +86,7 @@ var HttpClient = class {
86
86
  );
87
87
  }
88
88
  if (!hasDataEnvelope(json)) {
89
- throw new AinvokerError(
89
+ throw new AInvokerError(
90
90
  response.status,
91
91
  "INVALID_RESPONSE",
92
92
  "Response missing data envelope",
@@ -103,25 +103,24 @@ var TextResource = class {
103
103
  this.http = http;
104
104
  }
105
105
  http;
106
- /**
107
- * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).
108
- *
109
- * Authenticate with a project API key. `model` must be a `provider/model`
110
- * slug (e.g. `"openai/gpt-4o-mini"` or `"gemini/gemini-2.5-flash"`).
111
- */
112
106
  chat(params) {
113
- return this.http.post("/v1/text/chat", params);
107
+ const { provider, model, ...rest } = params;
108
+ const gatewayModel = provider !== void 0 && provider !== "" ? `${provider}/${model}` : model;
109
+ return this.http.post("/v1/text/chat", {
110
+ ...rest,
111
+ model: gatewayModel
112
+ });
114
113
  }
115
114
  };
116
115
 
117
116
  // src/client.ts
118
117
  var DEFAULT_BASE_URL = "https://ainvoker-api.onrender.com";
119
- var Ainvoker = class {
118
+ var AInvoker = class {
120
119
  /** Text modality (`/v1/text/...`). */
121
120
  text;
122
121
  constructor(options) {
123
122
  if (!options.apiKey || options.apiKey.trim().length === 0) {
124
- throw new Error("Ainvoker: apiKey is required");
123
+ throw new Error("AInvoker: apiKey is required");
125
124
  }
126
125
  const http = new HttpClient({
127
126
  apiKey: options.apiKey,
@@ -131,8 +130,8 @@ var Ainvoker = class {
131
130
  }
132
131
  };
133
132
 
134
- exports.Ainvoker = Ainvoker;
135
- exports.AinvokerError = AinvokerError;
136
- exports.isAinvokerError = isAinvokerError;
133
+ exports.AInvoker = AInvoker;
134
+ exports.AInvokerError = AInvokerError;
135
+ exports.isAInvokerError = isAInvokerError;
137
136
  //# sourceMappingURL=index.cjs.map
138
137
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/text.ts","../src/client.ts"],"names":[],"mappings":";;;AAqBO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EAC9B,MAAA;AAAA,EACA,IAAA;AAAA;AAAA,EAEA,IAAA;AAAA,EAET,WAAA,CACE,MAAA,EACA,IAAA,EACA,OAAA,EACA,OAAgB,MAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAGO,SAAS,gBAAgB,KAAA,EAAwC;AACtE,EAAA,OAAO,KAAA,YAAiB,aAAA;AAC1B;;;ACnCA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,KAAU,QAAA;AAC5C;AAEA,SAAS,kBAAkB,IAAA,EAAoE;AAC7F,EAAA,IAAI,CAAC,SAAS,IAAI,CAAA,IAAK,CAAC,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA,EAAG;AAC5C,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAI,IAAA,CAAK,KAAA;AAC/B,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,OAAO,YAAY,QAAA,EAAU;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAE,MAAM,OAAA,EAAQ;AACzB;AAEA,SAAS,gBAAgB,IAAA,EAA8C;AACrE,EAAA,OAAO,QAAA,CAAS,IAAI,CAAA,IAAK,MAAA,IAAU,IAAA;AACrC;AAEO,IAAM,aAAN,MAAiB;AAAA,EACL,MAAA;AAAA,EACA,OAAA;AAAA,EAEjB,YAAY,OAAA,EAA4B;AACtC,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAA,CAAQ,IAAA,EAAc,IAAA,EAA2B;AACrD,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,EAAG,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GAAI,IAAA,GAAO,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA,CAAA;AAEtE,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,MAAM,MAAM,GAAA,EAAK;AAAA,QAC1B,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,UACpC,cAAA,EAAgB,kBAAA;AAAA,UAChB,MAAA,EAAQ;AAAA,SACV;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,OAC1B,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,OAAA,GAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,wBAAA;AACzD,MAAA,MAAM,IAAI,aAAA,CAAc,CAAA,EAAG,eAAA,EAAiB,OAAO,CAAA;AAAA,IACrD;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,IAAI,IAAA,GAAgB,MAAA;AACpB,IAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,MAAA,IAAI;AACF,QAAA,IAAA,GAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,MACxB,CAAA,CAAA,MAAQ;AACN,QAAA,MAAM,IAAI,aAAA;AAAA,UACR,QAAA,CAAS,MAAA;AAAA,UACT,kBAAA;AAAA,UACA,kCAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,MAAA,GAAS,kBAAkB,IAAI,CAAA;AACrC,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,QAAA,CAAS,MAAA;AAAA,QACT,QAAQ,IAAA,IAAQ,YAAA;AAAA,QAChB,MAAA,EAAQ,OAAA,IAAW,CAAA,2BAAA,EAA8B,QAAA,CAAS,MAAM,CAAA,CAAA;AAAA,QAChE;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,eAAA,CAAgB,IAAI,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,QAAA,CAAS,MAAA;AAAA,QACT,kBAAA;AAAA,QACA,gCAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,EACd;AACF,CAAA;;;ACzFO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,IAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAmB;AAAA,EAAnB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,KAAK,MAAA,EAAiD;AACpD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAqB,eAAA,EAAiB,MAAM,CAAA;AAAA,EAC/D;AACF,CAAA;;;ACdA,IAAM,gBAAA,GAAmB,mCAAA;AAOlB,IAAM,WAAN,MAAe;AAAA;AAAA,EAEX,IAAA;AAAA,EAET,YAAY,OAAA,EAA0B;AACpC,IAAA,IAAI,CAAC,QAAQ,MAAA,IAAU,OAAA,CAAQ,OAAO,IAAA,EAAK,CAAE,WAAW,CAAA,EAAG;AACzD,MAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW;AAAA,MAC1B,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,OAAA,EAAS,QAAQ,OAAA,IAAW;AAAA,KAC7B,CAAA;AAED,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAI,CAAA;AAAA,EACnC;AACF","file":"index.cjs","sourcesContent":["/**\r\n * Known AInvoker API / SDK error codes.\r\n * Unknown server codes remain assignable via the open string union.\r\n */\r\nexport type AinvokerErrorCode =\r\n | \"UNAUTHORIZED\"\r\n | \"FORBIDDEN\"\r\n | \"NOT_FOUND\"\r\n | \"VALIDATION_ERROR\"\r\n | \"CONFLICT\"\r\n | \"UPSTREAM_ERROR\"\r\n | \"INTERNAL_ERROR\"\r\n | \"NETWORK_ERROR\"\r\n | \"INVALID_RESPONSE\"\r\n | \"HTTP_ERROR\"\r\n | (string & {})\r\n\r\n/**\r\n * Error thrown when the AInvoker API returns a non-success response\r\n * or the response body cannot be parsed as expected.\r\n */\r\nexport class AinvokerError extends Error {\r\n readonly status: number\r\n readonly code: AinvokerErrorCode\r\n /** Parsed response body when available (error envelope or raw JSON). */\r\n readonly body: unknown\r\n\r\n constructor(\r\n status: number,\r\n code: AinvokerErrorCode,\r\n message: string,\r\n body: unknown = undefined,\r\n ) {\r\n super(message)\r\n this.name = \"AinvokerError\"\r\n this.status = status\r\n this.code = code\r\n this.body = body\r\n }\r\n}\r\n\r\n/** Type guard for {@link AinvokerError}. */\r\nexport function isAinvokerError(error: unknown): error is AinvokerError {\r\n return error instanceof AinvokerError\r\n}\r\n","import { AinvokerError } from \"./errors.js\"\r\nimport type { AinvokerErrorCode } from \"./errors.js\"\r\nimport type { DataEnvelope } from \"./types.js\"\r\n\r\nexport interface HttpClientOptions {\r\n apiKey: string\r\n baseUrl: string\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return value !== null && typeof value === \"object\"\r\n}\r\n\r\nfunction parseErrorPayload(json: unknown): { code: AinvokerErrorCode; message: string } | null {\r\n if (!isRecord(json) || !isRecord(json.error)) {\r\n return null\r\n }\r\n const { code, message } = json.error\r\n if (typeof code !== \"string\" || typeof message !== \"string\") {\r\n return null\r\n }\r\n return { code, message }\r\n}\r\n\r\nfunction hasDataEnvelope(json: unknown): json is DataEnvelope<unknown> {\r\n return isRecord(json) && \"data\" in json\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string\r\n private readonly baseUrl: string\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.apiKey = options.apiKey\r\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\")\r\n }\r\n\r\n /**\r\n * POST JSON to a path under `baseUrl`. Unwraps `{ data: T }` on success.\r\n */\r\n async post<T>(path: string, body: unknown): Promise<T> {\r\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`\r\n\r\n let response: Response\r\n try {\r\n response = await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"application/json\",\r\n },\r\n body: JSON.stringify(body),\r\n })\r\n } catch (cause) {\r\n const message = cause instanceof Error ? cause.message : \"Network request failed\"\r\n throw new AinvokerError(0, \"NETWORK_ERROR\", message)\r\n }\r\n\r\n const text = await response.text()\r\n let json: unknown = undefined\r\n if (text.length > 0) {\r\n try {\r\n json = JSON.parse(text) as unknown\r\n } catch {\r\n throw new AinvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response body was not valid JSON\",\r\n text,\r\n )\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n const parsed = parseErrorPayload(json)\r\n throw new AinvokerError(\r\n response.status,\r\n parsed?.code ?? \"HTTP_ERROR\",\r\n parsed?.message ?? `Request failed with status ${response.status}`,\r\n json,\r\n )\r\n }\r\n\r\n if (!hasDataEnvelope(json)) {\r\n throw new AinvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response missing data envelope\",\r\n json,\r\n )\r\n }\r\n\r\n return json.data as T\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\"\r\nimport type { TextChatParams, TextChatResult } from \"../types.js\"\r\n\r\n/**\r\n * Text modality methods (`/v1/text/...`).\r\n */\r\nexport class TextResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /**\r\n * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).\r\n *\r\n * Authenticate with a project API key. `model` must be a `provider/model`\r\n * slug (e.g. `\"openai/gpt-4o-mini\"` or `\"gemini/gemini-2.5-flash\"`).\r\n */\r\n chat(params: TextChatParams): Promise<TextChatResult> {\r\n return this.http.post<TextChatResult>(\"/v1/text/chat\", params)\r\n }\r\n}\r\n","import { HttpClient } from \"./http.js\"\r\nimport { TextResource } from \"./resources/text.js\"\r\nimport type { AinvokerOptions } from \"./types.js\"\r\n\r\nconst DEFAULT_BASE_URL = \"https://ainvoker-api.onrender.com\"\r\n\r\n/**\r\n * Official AInvoker SDK client.\r\n *\r\n * Use modality namespaces such as {@link Ainvoker.text} for gateway calls.\r\n */\r\nexport class Ainvoker {\r\n /** Text modality (`/v1/text/...`). */\r\n readonly text: TextResource\r\n\r\n constructor(options: AinvokerOptions) {\r\n if (!options.apiKey || options.apiKey.trim().length === 0) {\r\n throw new Error(\"Ainvoker: apiKey is required\")\r\n }\r\n\r\n const http = new HttpClient({\r\n apiKey: options.apiKey,\r\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\r\n })\r\n\r\n this.text = new TextResource(http)\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/text.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Known AInvoker API / SDK error codes.\r\n * Unknown server codes remain assignable via the open string union.\r\n */\r\nexport type AInvokerErrorCode =\r\n | \"UNAUTHORIZED\"\r\n | \"FORBIDDEN\"\r\n | \"NOT_FOUND\"\r\n | \"VALIDATION_ERROR\"\r\n | \"CONFLICT\"\r\n | \"UPSTREAM_ERROR\"\r\n | \"INTERNAL_ERROR\"\r\n | \"NETWORK_ERROR\"\r\n | \"INVALID_RESPONSE\"\r\n | \"HTTP_ERROR\"\r\n | (string & {})\r\n\r\n/**\r\n * Error thrown when the AInvoker API returns a non-success response\r\n * or the response body cannot be parsed as expected.\r\n */\r\nexport class AInvokerError extends Error {\r\n readonly status: number\r\n readonly code: AInvokerErrorCode\r\n /** Parsed response body when available (error envelope or raw JSON). */\r\n readonly body: unknown\r\n\r\n constructor(\r\n status: number,\r\n code: AInvokerErrorCode,\r\n message: string,\r\n body: unknown = undefined,\r\n ) {\r\n super(message)\r\n this.name = \"AInvokerError\"\r\n this.status = status\r\n this.code = code\r\n this.body = body\r\n }\r\n}\r\n\r\n/** Type guard for {@link AInvokerError}. */\r\nexport function isAInvokerError(error: unknown): error is AInvokerError {\r\n return error instanceof AInvokerError\r\n}\r\n","import { AInvokerError } from \"./errors.js\"\r\nimport type { AInvokerErrorCode } from \"./errors.js\"\r\nimport type { DataEnvelope } from \"./types.js\"\r\n\r\nexport interface HttpClientOptions {\r\n apiKey: string\r\n baseUrl: string\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return value !== null && typeof value === \"object\"\r\n}\r\n\r\nfunction parseErrorPayload(json: unknown): { code: AInvokerErrorCode; message: string } | null {\r\n if (!isRecord(json) || !isRecord(json.error)) {\r\n return null\r\n }\r\n const { code, message } = json.error\r\n if (typeof code !== \"string\" || typeof message !== \"string\") {\r\n return null\r\n }\r\n return { code, message }\r\n}\r\n\r\nfunction hasDataEnvelope(json: unknown): json is DataEnvelope<unknown> {\r\n return isRecord(json) && \"data\" in json\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string\r\n private readonly baseUrl: string\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.apiKey = options.apiKey\r\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\")\r\n }\r\n\r\n /**\r\n * POST JSON to a path under `baseUrl`. Unwraps `{ data: T }` on success.\r\n */\r\n async post<T>(path: string, body: unknown): Promise<T> {\r\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`\r\n\r\n let response: Response\r\n try {\r\n response = await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"application/json\",\r\n },\r\n body: JSON.stringify(body),\r\n })\r\n } catch (cause) {\r\n const message = cause instanceof Error ? cause.message : \"Network request failed\"\r\n throw new AInvokerError(0, \"NETWORK_ERROR\", message)\r\n }\r\n\r\n const text = await response.text()\r\n let json: unknown = undefined\r\n if (text.length > 0) {\r\n try {\r\n json = JSON.parse(text) as unknown\r\n } catch {\r\n throw new AInvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response body was not valid JSON\",\r\n text,\r\n )\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n const parsed = parseErrorPayload(json)\r\n throw new AInvokerError(\r\n response.status,\r\n parsed?.code ?? \"HTTP_ERROR\",\r\n parsed?.message ?? `Request failed with status ${response.status}`,\r\n json,\r\n )\r\n }\r\n\r\n if (!hasDataEnvelope(json)) {\r\n throw new AInvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response missing data envelope\",\r\n json,\r\n )\r\n }\r\n\r\n return json.data as T\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\"\r\nimport type {\r\n TextChatEscapeParams,\r\n TextChatParams,\r\n TextChatResult,\r\n} from \"../types.js\"\r\n\r\n/**\r\n * Text modality methods (`/v1/text/...`).\r\n */\r\nexport class TextResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /**\r\n * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).\r\n *\r\n * Pass `provider` and `model` for typed autocomplete. When `provider` is set,\r\n * the SDK joins them into a `provider/model` slug. When `provider` is omitted,\r\n * the bare `model` name is sent and the API resolves it.\r\n */\r\n chat(params: TextChatParams): Promise<TextChatResult>\r\n chat<P extends string, M extends string>(\r\n params: TextChatEscapeParams<P, M>,\r\n ): Promise<TextChatResult>\r\n chat(\r\n params: TextChatParams | TextChatEscapeParams<string, string>,\r\n ): Promise<TextChatResult> {\r\n const { provider, model, ...rest } = params\r\n const gatewayModel =\r\n provider !== undefined && provider !== \"\"\r\n ? `${provider}/${model}`\r\n : model\r\n\r\n return this.http.post<TextChatResult>(\"/v1/text/chat\", {\r\n ...rest,\r\n model: gatewayModel,\r\n })\r\n }\r\n}\r\n","import { HttpClient } from \"./http.js\"\r\nimport { TextResource } from \"./resources/text.js\"\r\nimport type { AInvokerOptions } from \"./types.js\"\r\n\r\nconst DEFAULT_BASE_URL = \"https://ainvoker-api.onrender.com\"\r\n\r\n/**\r\n * Official AInvoker SDK client.\r\n *\r\n * Use modality namespaces such as {@link AInvoker.text} for gateway calls.\r\n */\r\nexport class AInvoker {\r\n /** Text modality (`/v1/text/...`). */\r\n readonly text: TextResource\r\n\r\n constructor(options: AInvokerOptions) {\r\n if (!options.apiKey || options.apiKey.trim().length === 0) {\r\n throw new Error(\"AInvoker: apiKey is required\")\r\n }\r\n\r\n const http = new HttpClient({\r\n apiKey: options.apiKey,\r\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\r\n })\r\n\r\n this.text = new TextResource(http)\r\n }\r\n}\r\n"]}
package/dist/index.d.cts CHANGED
@@ -13,9 +13,9 @@ declare class HttpClient {
13
13
  }
14
14
 
15
15
  /**
16
- * Client configuration for {@link Ainvoker}.
16
+ * Client configuration for {@link AInvoker}.
17
17
  */
18
- interface AinvokerOptions {
18
+ interface AInvokerOptions {
19
19
  /**
20
20
  * Project API key (`ain_…`).
21
21
  * Sent as `Authorization: Bearer <apiKey>`.
@@ -35,19 +35,62 @@ interface ChatMessage {
35
35
  content: string;
36
36
  }
37
37
  /**
38
- * Parameters for {@link TextResource.chat}.
38
+ * Hardcoded text catalog (provider → models). Keep in sync with the API seed.
39
+ * Do not fetch models to generate these types.
39
40
  */
40
- interface TextChatParams {
41
- /**
42
- * Provider model slug, e.g. `"openai/gpt-4o-mini"` or `"gemini/gemini-2.5-flash"`.
43
- */
44
- model: string;
41
+ type TextCatalog = {
42
+ openai: "gpt-4o-mini";
43
+ gemini: "gemini-3.6-flash";
44
+ };
45
+ type TextProvider = keyof TextCatalog;
46
+ type TextModel = TextCatalog[TextProvider];
47
+ /** Exact provider/model pairs for bidirectional autocomplete. */
48
+ type TextCatalogPair = {
49
+ [P in TextProvider]: {
50
+ provider: P;
51
+ model: TextCatalog[P];
52
+ };
53
+ }[TextProvider];
54
+ type TextChatFields = {
45
55
  messages: ChatMessage[];
46
56
  /** Sampling temperature (0–2). */
47
57
  temperature?: number;
48
- /** Maximum tokens to generate. */
58
+ /**
59
+ * Maximum tokens to generate.
60
+ * When omitted, the gateway reserves and caps output at 8192.
61
+ */
49
62
  maxTokens?: number;
50
- }
63
+ };
64
+ /**
65
+ * Provider omitted: model may be any catalog name (or a future API name).
66
+ * The SDK sends the bare model string; the API resolves it.
67
+ */
68
+ type TextChatWithoutProvider = {
69
+ provider?: undefined;
70
+ model: TextModel | (string & {});
71
+ } & TextChatFields;
72
+ /**
73
+ * Parameters for {@link TextResource.chat}.
74
+ *
75
+ * In the same object literal:
76
+ * - Neither field written: both suggest the full catalog.
77
+ * - `provider` set: `model` narrows to that provider’s models.
78
+ * - `model` set: `provider` narrows to providers that have that model.
79
+ */
80
+ type TextChatParams = (TextCatalogPair & TextChatFields) | TextChatWithoutProvider;
81
+ /**
82
+ * Reject known catalog mismatches while allowing unknown strings for forward compat.
83
+ */
84
+ type TextChatEscapeParams<P extends string = string, M extends string = string> = P extends TextProvider ? M extends TextModel ? M extends TextCatalog[P] ? {
85
+ provider: P;
86
+ model: M;
87
+ } & TextChatFields : never : {
88
+ provider: P;
89
+ model: M;
90
+ } & TextChatFields : {
91
+ provider: P;
92
+ model: M;
93
+ } & TextChatFields;
51
94
  /**
52
95
  * Token usage reported by the gateway (may be null).
53
96
  */
@@ -75,40 +118,42 @@ declare class TextResource {
75
118
  /**
76
119
  * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).
77
120
  *
78
- * Authenticate with a project API key. `model` must be a `provider/model`
79
- * slug (e.g. `"openai/gpt-4o-mini"` or `"gemini/gemini-2.5-flash"`).
121
+ * Pass `provider` and `model` for typed autocomplete. When `provider` is set,
122
+ * the SDK joins them into a `provider/model` slug. When `provider` is omitted,
123
+ * the bare `model` name is sent and the API resolves it.
80
124
  */
81
125
  chat(params: TextChatParams): Promise<TextChatResult>;
126
+ chat<P extends string, M extends string>(params: TextChatEscapeParams<P, M>): Promise<TextChatResult>;
82
127
  }
83
128
 
84
129
  /**
85
130
  * Official AInvoker SDK client.
86
131
  *
87
- * Use modality namespaces such as {@link Ainvoker.text} for gateway calls.
132
+ * Use modality namespaces such as {@link AInvoker.text} for gateway calls.
88
133
  */
89
- declare class Ainvoker {
134
+ declare class AInvoker {
90
135
  /** Text modality (`/v1/text/...`). */
91
136
  readonly text: TextResource;
92
- constructor(options: AinvokerOptions);
137
+ constructor(options: AInvokerOptions);
93
138
  }
94
139
 
95
140
  /**
96
141
  * Known AInvoker API / SDK error codes.
97
142
  * Unknown server codes remain assignable via the open string union.
98
143
  */
99
- type AinvokerErrorCode = "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "VALIDATION_ERROR" | "CONFLICT" | "UPSTREAM_ERROR" | "INTERNAL_ERROR" | "NETWORK_ERROR" | "INVALID_RESPONSE" | "HTTP_ERROR" | (string & {});
144
+ type AInvokerErrorCode = "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "VALIDATION_ERROR" | "CONFLICT" | "UPSTREAM_ERROR" | "INTERNAL_ERROR" | "NETWORK_ERROR" | "INVALID_RESPONSE" | "HTTP_ERROR" | (string & {});
100
145
  /**
101
146
  * Error thrown when the AInvoker API returns a non-success response
102
147
  * or the response body cannot be parsed as expected.
103
148
  */
104
- declare class AinvokerError extends Error {
149
+ declare class AInvokerError extends Error {
105
150
  readonly status: number;
106
- readonly code: AinvokerErrorCode;
151
+ readonly code: AInvokerErrorCode;
107
152
  /** Parsed response body when available (error envelope or raw JSON). */
108
153
  readonly body: unknown;
109
- constructor(status: number, code: AinvokerErrorCode, message: string, body?: unknown);
154
+ constructor(status: number, code: AInvokerErrorCode, message: string, body?: unknown);
110
155
  }
111
- /** Type guard for {@link AinvokerError}. */
112
- declare function isAinvokerError(error: unknown): error is AinvokerError;
156
+ /** Type guard for {@link AInvokerError}. */
157
+ declare function isAInvokerError(error: unknown): error is AInvokerError;
113
158
 
114
- export { Ainvoker, AinvokerError, type AinvokerErrorCode, type AinvokerOptions, type ChatMessage, type ChatUsage, type TextChatParams, type TextChatResult, isAinvokerError };
159
+ export { AInvoker, AInvokerError, type AInvokerErrorCode, type AInvokerOptions, type ChatMessage, type ChatUsage, type TextCatalog, type TextCatalogPair, type TextChatEscapeParams, type TextChatParams, type TextChatResult, type TextModel, type TextProvider, isAInvokerError };
package/dist/index.d.ts CHANGED
@@ -13,9 +13,9 @@ declare class HttpClient {
13
13
  }
14
14
 
15
15
  /**
16
- * Client configuration for {@link Ainvoker}.
16
+ * Client configuration for {@link AInvoker}.
17
17
  */
18
- interface AinvokerOptions {
18
+ interface AInvokerOptions {
19
19
  /**
20
20
  * Project API key (`ain_…`).
21
21
  * Sent as `Authorization: Bearer <apiKey>`.
@@ -35,19 +35,62 @@ interface ChatMessage {
35
35
  content: string;
36
36
  }
37
37
  /**
38
- * Parameters for {@link TextResource.chat}.
38
+ * Hardcoded text catalog (provider → models). Keep in sync with the API seed.
39
+ * Do not fetch models to generate these types.
39
40
  */
40
- interface TextChatParams {
41
- /**
42
- * Provider model slug, e.g. `"openai/gpt-4o-mini"` or `"gemini/gemini-2.5-flash"`.
43
- */
44
- model: string;
41
+ type TextCatalog = {
42
+ openai: "gpt-4o-mini";
43
+ gemini: "gemini-3.6-flash";
44
+ };
45
+ type TextProvider = keyof TextCatalog;
46
+ type TextModel = TextCatalog[TextProvider];
47
+ /** Exact provider/model pairs for bidirectional autocomplete. */
48
+ type TextCatalogPair = {
49
+ [P in TextProvider]: {
50
+ provider: P;
51
+ model: TextCatalog[P];
52
+ };
53
+ }[TextProvider];
54
+ type TextChatFields = {
45
55
  messages: ChatMessage[];
46
56
  /** Sampling temperature (0–2). */
47
57
  temperature?: number;
48
- /** Maximum tokens to generate. */
58
+ /**
59
+ * Maximum tokens to generate.
60
+ * When omitted, the gateway reserves and caps output at 8192.
61
+ */
49
62
  maxTokens?: number;
50
- }
63
+ };
64
+ /**
65
+ * Provider omitted: model may be any catalog name (or a future API name).
66
+ * The SDK sends the bare model string; the API resolves it.
67
+ */
68
+ type TextChatWithoutProvider = {
69
+ provider?: undefined;
70
+ model: TextModel | (string & {});
71
+ } & TextChatFields;
72
+ /**
73
+ * Parameters for {@link TextResource.chat}.
74
+ *
75
+ * In the same object literal:
76
+ * - Neither field written: both suggest the full catalog.
77
+ * - `provider` set: `model` narrows to that provider’s models.
78
+ * - `model` set: `provider` narrows to providers that have that model.
79
+ */
80
+ type TextChatParams = (TextCatalogPair & TextChatFields) | TextChatWithoutProvider;
81
+ /**
82
+ * Reject known catalog mismatches while allowing unknown strings for forward compat.
83
+ */
84
+ type TextChatEscapeParams<P extends string = string, M extends string = string> = P extends TextProvider ? M extends TextModel ? M extends TextCatalog[P] ? {
85
+ provider: P;
86
+ model: M;
87
+ } & TextChatFields : never : {
88
+ provider: P;
89
+ model: M;
90
+ } & TextChatFields : {
91
+ provider: P;
92
+ model: M;
93
+ } & TextChatFields;
51
94
  /**
52
95
  * Token usage reported by the gateway (may be null).
53
96
  */
@@ -75,40 +118,42 @@ declare class TextResource {
75
118
  /**
76
119
  * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).
77
120
  *
78
- * Authenticate with a project API key. `model` must be a `provider/model`
79
- * slug (e.g. `"openai/gpt-4o-mini"` or `"gemini/gemini-2.5-flash"`).
121
+ * Pass `provider` and `model` for typed autocomplete. When `provider` is set,
122
+ * the SDK joins them into a `provider/model` slug. When `provider` is omitted,
123
+ * the bare `model` name is sent and the API resolves it.
80
124
  */
81
125
  chat(params: TextChatParams): Promise<TextChatResult>;
126
+ chat<P extends string, M extends string>(params: TextChatEscapeParams<P, M>): Promise<TextChatResult>;
82
127
  }
83
128
 
84
129
  /**
85
130
  * Official AInvoker SDK client.
86
131
  *
87
- * Use modality namespaces such as {@link Ainvoker.text} for gateway calls.
132
+ * Use modality namespaces such as {@link AInvoker.text} for gateway calls.
88
133
  */
89
- declare class Ainvoker {
134
+ declare class AInvoker {
90
135
  /** Text modality (`/v1/text/...`). */
91
136
  readonly text: TextResource;
92
- constructor(options: AinvokerOptions);
137
+ constructor(options: AInvokerOptions);
93
138
  }
94
139
 
95
140
  /**
96
141
  * Known AInvoker API / SDK error codes.
97
142
  * Unknown server codes remain assignable via the open string union.
98
143
  */
99
- type AinvokerErrorCode = "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "VALIDATION_ERROR" | "CONFLICT" | "UPSTREAM_ERROR" | "INTERNAL_ERROR" | "NETWORK_ERROR" | "INVALID_RESPONSE" | "HTTP_ERROR" | (string & {});
144
+ type AInvokerErrorCode = "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "VALIDATION_ERROR" | "CONFLICT" | "UPSTREAM_ERROR" | "INTERNAL_ERROR" | "NETWORK_ERROR" | "INVALID_RESPONSE" | "HTTP_ERROR" | (string & {});
100
145
  /**
101
146
  * Error thrown when the AInvoker API returns a non-success response
102
147
  * or the response body cannot be parsed as expected.
103
148
  */
104
- declare class AinvokerError extends Error {
149
+ declare class AInvokerError extends Error {
105
150
  readonly status: number;
106
- readonly code: AinvokerErrorCode;
151
+ readonly code: AInvokerErrorCode;
107
152
  /** Parsed response body when available (error envelope or raw JSON). */
108
153
  readonly body: unknown;
109
- constructor(status: number, code: AinvokerErrorCode, message: string, body?: unknown);
154
+ constructor(status: number, code: AInvokerErrorCode, message: string, body?: unknown);
110
155
  }
111
- /** Type guard for {@link AinvokerError}. */
112
- declare function isAinvokerError(error: unknown): error is AinvokerError;
156
+ /** Type guard for {@link AInvokerError}. */
157
+ declare function isAInvokerError(error: unknown): error is AInvokerError;
113
158
 
114
- export { Ainvoker, AinvokerError, type AinvokerErrorCode, type AinvokerOptions, type ChatMessage, type ChatUsage, type TextChatParams, type TextChatResult, isAinvokerError };
159
+ export { AInvoker, AInvokerError, type AInvokerErrorCode, type AInvokerOptions, type ChatMessage, type ChatUsage, type TextCatalog, type TextCatalogPair, type TextChatEscapeParams, type TextChatParams, type TextChatResult, type TextModel, type TextProvider, isAInvokerError };
package/dist/index.js CHANGED
@@ -1,19 +1,19 @@
1
1
  // src/errors.ts
2
- var AinvokerError = class extends Error {
2
+ var AInvokerError = class extends Error {
3
3
  status;
4
4
  code;
5
5
  /** Parsed response body when available (error envelope or raw JSON). */
6
6
  body;
7
7
  constructor(status, code, message, body = void 0) {
8
8
  super(message);
9
- this.name = "AinvokerError";
9
+ this.name = "AInvokerError";
10
10
  this.status = status;
11
11
  this.code = code;
12
12
  this.body = body;
13
13
  }
14
14
  };
15
- function isAinvokerError(error) {
16
- return error instanceof AinvokerError;
15
+ function isAInvokerError(error) {
16
+ return error instanceof AInvokerError;
17
17
  }
18
18
 
19
19
  // src/http.ts
@@ -58,7 +58,7 @@ var HttpClient = class {
58
58
  });
59
59
  } catch (cause) {
60
60
  const message = cause instanceof Error ? cause.message : "Network request failed";
61
- throw new AinvokerError(0, "NETWORK_ERROR", message);
61
+ throw new AInvokerError(0, "NETWORK_ERROR", message);
62
62
  }
63
63
  const text = await response.text();
64
64
  let json = void 0;
@@ -66,7 +66,7 @@ var HttpClient = class {
66
66
  try {
67
67
  json = JSON.parse(text);
68
68
  } catch {
69
- throw new AinvokerError(
69
+ throw new AInvokerError(
70
70
  response.status,
71
71
  "INVALID_RESPONSE",
72
72
  "Response body was not valid JSON",
@@ -76,7 +76,7 @@ var HttpClient = class {
76
76
  }
77
77
  if (!response.ok) {
78
78
  const parsed = parseErrorPayload(json);
79
- throw new AinvokerError(
79
+ throw new AInvokerError(
80
80
  response.status,
81
81
  parsed?.code ?? "HTTP_ERROR",
82
82
  parsed?.message ?? `Request failed with status ${response.status}`,
@@ -84,7 +84,7 @@ var HttpClient = class {
84
84
  );
85
85
  }
86
86
  if (!hasDataEnvelope(json)) {
87
- throw new AinvokerError(
87
+ throw new AInvokerError(
88
88
  response.status,
89
89
  "INVALID_RESPONSE",
90
90
  "Response missing data envelope",
@@ -101,25 +101,24 @@ var TextResource = class {
101
101
  this.http = http;
102
102
  }
103
103
  http;
104
- /**
105
- * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).
106
- *
107
- * Authenticate with a project API key. `model` must be a `provider/model`
108
- * slug (e.g. `"openai/gpt-4o-mini"` or `"gemini/gemini-2.5-flash"`).
109
- */
110
104
  chat(params) {
111
- return this.http.post("/v1/text/chat", params);
105
+ const { provider, model, ...rest } = params;
106
+ const gatewayModel = provider !== void 0 && provider !== "" ? `${provider}/${model}` : model;
107
+ return this.http.post("/v1/text/chat", {
108
+ ...rest,
109
+ model: gatewayModel
110
+ });
112
111
  }
113
112
  };
114
113
 
115
114
  // src/client.ts
116
115
  var DEFAULT_BASE_URL = "https://ainvoker-api.onrender.com";
117
- var Ainvoker = class {
116
+ var AInvoker = class {
118
117
  /** Text modality (`/v1/text/...`). */
119
118
  text;
120
119
  constructor(options) {
121
120
  if (!options.apiKey || options.apiKey.trim().length === 0) {
122
- throw new Error("Ainvoker: apiKey is required");
121
+ throw new Error("AInvoker: apiKey is required");
123
122
  }
124
123
  const http = new HttpClient({
125
124
  apiKey: options.apiKey,
@@ -129,6 +128,6 @@ var Ainvoker = class {
129
128
  }
130
129
  };
131
130
 
132
- export { Ainvoker, AinvokerError, isAinvokerError };
131
+ export { AInvoker, AInvokerError, isAInvokerError };
133
132
  //# sourceMappingURL=index.js.map
134
133
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/text.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Known AInvoker API / SDK error codes.\r\n * Unknown server codes remain assignable via the open string union.\r\n */\r\nexport type AinvokerErrorCode =\r\n | \"UNAUTHORIZED\"\r\n | \"FORBIDDEN\"\r\n | \"NOT_FOUND\"\r\n | \"VALIDATION_ERROR\"\r\n | \"CONFLICT\"\r\n | \"UPSTREAM_ERROR\"\r\n | \"INTERNAL_ERROR\"\r\n | \"NETWORK_ERROR\"\r\n | \"INVALID_RESPONSE\"\r\n | \"HTTP_ERROR\"\r\n | (string & {})\r\n\r\n/**\r\n * Error thrown when the AInvoker API returns a non-success response\r\n * or the response body cannot be parsed as expected.\r\n */\r\nexport class AinvokerError extends Error {\r\n readonly status: number\r\n readonly code: AinvokerErrorCode\r\n /** Parsed response body when available (error envelope or raw JSON). */\r\n readonly body: unknown\r\n\r\n constructor(\r\n status: number,\r\n code: AinvokerErrorCode,\r\n message: string,\r\n body: unknown = undefined,\r\n ) {\r\n super(message)\r\n this.name = \"AinvokerError\"\r\n this.status = status\r\n this.code = code\r\n this.body = body\r\n }\r\n}\r\n\r\n/** Type guard for {@link AinvokerError}. */\r\nexport function isAinvokerError(error: unknown): error is AinvokerError {\r\n return error instanceof AinvokerError\r\n}\r\n","import { AinvokerError } from \"./errors.js\"\r\nimport type { AinvokerErrorCode } from \"./errors.js\"\r\nimport type { DataEnvelope } from \"./types.js\"\r\n\r\nexport interface HttpClientOptions {\r\n apiKey: string\r\n baseUrl: string\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return value !== null && typeof value === \"object\"\r\n}\r\n\r\nfunction parseErrorPayload(json: unknown): { code: AinvokerErrorCode; message: string } | null {\r\n if (!isRecord(json) || !isRecord(json.error)) {\r\n return null\r\n }\r\n const { code, message } = json.error\r\n if (typeof code !== \"string\" || typeof message !== \"string\") {\r\n return null\r\n }\r\n return { code, message }\r\n}\r\n\r\nfunction hasDataEnvelope(json: unknown): json is DataEnvelope<unknown> {\r\n return isRecord(json) && \"data\" in json\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string\r\n private readonly baseUrl: string\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.apiKey = options.apiKey\r\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\")\r\n }\r\n\r\n /**\r\n * POST JSON to a path under `baseUrl`. Unwraps `{ data: T }` on success.\r\n */\r\n async post<T>(path: string, body: unknown): Promise<T> {\r\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`\r\n\r\n let response: Response\r\n try {\r\n response = await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"application/json\",\r\n },\r\n body: JSON.stringify(body),\r\n })\r\n } catch (cause) {\r\n const message = cause instanceof Error ? cause.message : \"Network request failed\"\r\n throw new AinvokerError(0, \"NETWORK_ERROR\", message)\r\n }\r\n\r\n const text = await response.text()\r\n let json: unknown = undefined\r\n if (text.length > 0) {\r\n try {\r\n json = JSON.parse(text) as unknown\r\n } catch {\r\n throw new AinvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response body was not valid JSON\",\r\n text,\r\n )\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n const parsed = parseErrorPayload(json)\r\n throw new AinvokerError(\r\n response.status,\r\n parsed?.code ?? \"HTTP_ERROR\",\r\n parsed?.message ?? `Request failed with status ${response.status}`,\r\n json,\r\n )\r\n }\r\n\r\n if (!hasDataEnvelope(json)) {\r\n throw new AinvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response missing data envelope\",\r\n json,\r\n )\r\n }\r\n\r\n return json.data as T\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\"\r\nimport type { TextChatParams, TextChatResult } from \"../types.js\"\r\n\r\n/**\r\n * Text modality methods (`/v1/text/...`).\r\n */\r\nexport class TextResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /**\r\n * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).\r\n *\r\n * Authenticate with a project API key. `model` must be a `provider/model`\r\n * slug (e.g. `\"openai/gpt-4o-mini\"` or `\"gemini/gemini-2.5-flash\"`).\r\n */\r\n chat(params: TextChatParams): Promise<TextChatResult> {\r\n return this.http.post<TextChatResult>(\"/v1/text/chat\", params)\r\n }\r\n}\r\n","import { HttpClient } from \"./http.js\"\r\nimport { TextResource } from \"./resources/text.js\"\r\nimport type { AinvokerOptions } from \"./types.js\"\r\n\r\nconst DEFAULT_BASE_URL = \"https://ainvoker-api.onrender.com\"\r\n\r\n/**\r\n * Official AInvoker SDK client.\r\n *\r\n * Use modality namespaces such as {@link Ainvoker.text} for gateway calls.\r\n */\r\nexport class Ainvoker {\r\n /** Text modality (`/v1/text/...`). */\r\n readonly text: TextResource\r\n\r\n constructor(options: AinvokerOptions) {\r\n if (!options.apiKey || options.apiKey.trim().length === 0) {\r\n throw new Error(\"Ainvoker: apiKey is required\")\r\n }\r\n\r\n const http = new HttpClient({\r\n apiKey: options.apiKey,\r\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\r\n })\r\n\r\n this.text = new TextResource(http)\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/text.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Known AInvoker API / SDK error codes.\r\n * Unknown server codes remain assignable via the open string union.\r\n */\r\nexport type AInvokerErrorCode =\r\n | \"UNAUTHORIZED\"\r\n | \"FORBIDDEN\"\r\n | \"NOT_FOUND\"\r\n | \"VALIDATION_ERROR\"\r\n | \"CONFLICT\"\r\n | \"UPSTREAM_ERROR\"\r\n | \"INTERNAL_ERROR\"\r\n | \"NETWORK_ERROR\"\r\n | \"INVALID_RESPONSE\"\r\n | \"HTTP_ERROR\"\r\n | (string & {})\r\n\r\n/**\r\n * Error thrown when the AInvoker API returns a non-success response\r\n * or the response body cannot be parsed as expected.\r\n */\r\nexport class AInvokerError extends Error {\r\n readonly status: number\r\n readonly code: AInvokerErrorCode\r\n /** Parsed response body when available (error envelope or raw JSON). */\r\n readonly body: unknown\r\n\r\n constructor(\r\n status: number,\r\n code: AInvokerErrorCode,\r\n message: string,\r\n body: unknown = undefined,\r\n ) {\r\n super(message)\r\n this.name = \"AInvokerError\"\r\n this.status = status\r\n this.code = code\r\n this.body = body\r\n }\r\n}\r\n\r\n/** Type guard for {@link AInvokerError}. */\r\nexport function isAInvokerError(error: unknown): error is AInvokerError {\r\n return error instanceof AInvokerError\r\n}\r\n","import { AInvokerError } from \"./errors.js\"\r\nimport type { AInvokerErrorCode } from \"./errors.js\"\r\nimport type { DataEnvelope } from \"./types.js\"\r\n\r\nexport interface HttpClientOptions {\r\n apiKey: string\r\n baseUrl: string\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return value !== null && typeof value === \"object\"\r\n}\r\n\r\nfunction parseErrorPayload(json: unknown): { code: AInvokerErrorCode; message: string } | null {\r\n if (!isRecord(json) || !isRecord(json.error)) {\r\n return null\r\n }\r\n const { code, message } = json.error\r\n if (typeof code !== \"string\" || typeof message !== \"string\") {\r\n return null\r\n }\r\n return { code, message }\r\n}\r\n\r\nfunction hasDataEnvelope(json: unknown): json is DataEnvelope<unknown> {\r\n return isRecord(json) && \"data\" in json\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string\r\n private readonly baseUrl: string\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.apiKey = options.apiKey\r\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\")\r\n }\r\n\r\n /**\r\n * POST JSON to a path under `baseUrl`. Unwraps `{ data: T }` on success.\r\n */\r\n async post<T>(path: string, body: unknown): Promise<T> {\r\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`\r\n\r\n let response: Response\r\n try {\r\n response = await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"application/json\",\r\n },\r\n body: JSON.stringify(body),\r\n })\r\n } catch (cause) {\r\n const message = cause instanceof Error ? cause.message : \"Network request failed\"\r\n throw new AInvokerError(0, \"NETWORK_ERROR\", message)\r\n }\r\n\r\n const text = await response.text()\r\n let json: unknown = undefined\r\n if (text.length > 0) {\r\n try {\r\n json = JSON.parse(text) as unknown\r\n } catch {\r\n throw new AInvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response body was not valid JSON\",\r\n text,\r\n )\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n const parsed = parseErrorPayload(json)\r\n throw new AInvokerError(\r\n response.status,\r\n parsed?.code ?? \"HTTP_ERROR\",\r\n parsed?.message ?? `Request failed with status ${response.status}`,\r\n json,\r\n )\r\n }\r\n\r\n if (!hasDataEnvelope(json)) {\r\n throw new AInvokerError(\r\n response.status,\r\n \"INVALID_RESPONSE\",\r\n \"Response missing data envelope\",\r\n json,\r\n )\r\n }\r\n\r\n return json.data as T\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\"\r\nimport type {\r\n TextChatEscapeParams,\r\n TextChatParams,\r\n TextChatResult,\r\n} from \"../types.js\"\r\n\r\n/**\r\n * Text modality methods (`/v1/text/...`).\r\n */\r\nexport class TextResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /**\r\n * Text chat completion via the AInvoker gateway (`POST /v1/text/chat`).\r\n *\r\n * Pass `provider` and `model` for typed autocomplete. When `provider` is set,\r\n * the SDK joins them into a `provider/model` slug. When `provider` is omitted,\r\n * the bare `model` name is sent and the API resolves it.\r\n */\r\n chat(params: TextChatParams): Promise<TextChatResult>\r\n chat<P extends string, M extends string>(\r\n params: TextChatEscapeParams<P, M>,\r\n ): Promise<TextChatResult>\r\n chat(\r\n params: TextChatParams | TextChatEscapeParams<string, string>,\r\n ): Promise<TextChatResult> {\r\n const { provider, model, ...rest } = params\r\n const gatewayModel =\r\n provider !== undefined && provider !== \"\"\r\n ? `${provider}/${model}`\r\n : model\r\n\r\n return this.http.post<TextChatResult>(\"/v1/text/chat\", {\r\n ...rest,\r\n model: gatewayModel,\r\n })\r\n }\r\n}\r\n","import { HttpClient } from \"./http.js\"\r\nimport { TextResource } from \"./resources/text.js\"\r\nimport type { AInvokerOptions } from \"./types.js\"\r\n\r\nconst DEFAULT_BASE_URL = \"https://ainvoker-api.onrender.com\"\r\n\r\n/**\r\n * Official AInvoker SDK client.\r\n *\r\n * Use modality namespaces such as {@link AInvoker.text} for gateway calls.\r\n */\r\nexport class AInvoker {\r\n /** Text modality (`/v1/text/...`). */\r\n readonly text: TextResource\r\n\r\n constructor(options: AInvokerOptions) {\r\n if (!options.apiKey || options.apiKey.trim().length === 0) {\r\n throw new Error(\"AInvoker: apiKey is required\")\r\n }\r\n\r\n const http = new HttpClient({\r\n apiKey: options.apiKey,\r\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\r\n })\r\n\r\n this.text = new TextResource(http)\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ainvoker",
3
- "version": "1.0.2",
3
+ "version": "3.0.0",
4
4
  "description": "Official TypeScript/JavaScript SDK for the AInvoker AI gateway",
5
5
  "license": "MIT",
6
6
  "author": "AInvoker",