@akumi/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 ADDED
@@ -0,0 +1,87 @@
1
+ # Akumi TypeScript SDK
2
+
3
+ The official TypeScript client for [Akumi](https://akumi.cloud), the
4
+ EU-sovereign, OpenAI-compatible inference API. Native `fetch`, zero runtime
5
+ dependencies. One `base_url` for every model, governed and metered, with your
6
+ regulated data kept in the EU.
7
+
8
+ - **Drop-in OpenAI-compatible.** Chat completions, embeddings, and models under one key.
9
+ - **EU-sovereign by default.** The egress guard fails closed on non-EU routing.
10
+ - **Governed, not just hosted.** PII firewall, per-request residency, and a metadata-only audit trail on every call.
11
+ - **Dependable.** Async streaming and automatic retries on transient errors.
12
+
13
+ ## Requirements
14
+
15
+ Node 18 or newer.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install @akumi/sdk
21
+ ```
22
+
23
+ ## Quickstart
24
+
25
+ Create an API key under app.akumi.cloud -> Platform -> API keys:
26
+
27
+ ```ts
28
+ import { Akumi } from "@akumi/sdk";
29
+
30
+ const akumi = Akumi.fromApiKey("mk_...");
31
+
32
+ const response = (await akumi.chat.create({
33
+ model: "mistral/mistral-large-latest",
34
+ messages: [{ role: "user", content: "Explain EU data residency in one sentence." }],
35
+ })) as { choices: { message: { content: string } }[] };
36
+
37
+ console.log(response.choices[0].message.content);
38
+ ```
39
+
40
+ ## Streaming
41
+
42
+ `createStreamed()` yields OpenAI-compatible chunks:
43
+
44
+ ```ts
45
+ for await (const chunk of akumi.chat.createStreamed({
46
+ model: "mistral/mistral-large-latest",
47
+ messages: [{ role: "user", content: "Write a haiku about Frankfurt." }],
48
+ })) {
49
+ const c = chunk as { choices: { delta: { content?: string } }[] };
50
+ process.stdout.write(c.choices[0]?.delta?.content ?? "");
51
+ }
52
+ ```
53
+
54
+ ## Embeddings
55
+
56
+ ```ts
57
+ const embeddings = (await akumi.embeddings.create({
58
+ model: "mistral/mistral-embed",
59
+ input: "The quarterly report is ready for review.",
60
+ })) as { data: { embedding: number[] }[] };
61
+
62
+ const vector = embeddings.data[0].embedding;
63
+ ```
64
+
65
+ ## More resources
66
+
67
+ - `akumi.models.list()` lists the models available to your key.
68
+ - `akumi.memory.forget(...)` and `akumi.memoryThreads.list()` manage long-term memory and threads.
69
+ - `akumi.auditLogs.list()` reads your metadata-only audit trail.
70
+
71
+ ## Configuration
72
+
73
+ `fromApiKey()` targets `https://api.akumi.cloud/v1` and retries transient
74
+ failures (429, 502, 503, 504). Pass a config object to override the base URL,
75
+ timeout, or retry policy.
76
+
77
+ ## Documentation
78
+
79
+ - Guides: https://akumi.cloud/docs
80
+ - API reference: https://akumi.cloud/docs/api-reference
81
+
82
+ ## About
83
+
84
+ Generated from the Akumi OpenAPI specification, so it tracks the API
85
+ automatically. Issues: https://github.com/akumi-cloud/ts-sdk.
86
+
87
+ MIT licensed.
package/dist/index.cjs ADDED
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Akumi: () => Akumi,
24
+ AkumiError: () => AkumiError,
25
+ ApiError: () => ApiError,
26
+ AuditLogsResource: () => AuditLogsResource,
27
+ AuthenticationError: () => AuthenticationError,
28
+ ChatResource: () => ChatResource,
29
+ EmbeddingsResource: () => EmbeddingsResource,
30
+ InvalidRequestError: () => InvalidRequestError,
31
+ ModelsResource: () => ModelsResource,
32
+ RateLimitError: () => RateLimitError,
33
+ RecallResource: () => RecallResource
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/errors.ts
38
+ var AkumiError = class extends Error {
39
+ constructor(message) {
40
+ super(message);
41
+ this.name = new.target.name;
42
+ }
43
+ };
44
+ var ApiError = class extends AkumiError {
45
+ status;
46
+ body;
47
+ constructor(message, status, body = {}) {
48
+ super(message);
49
+ this.status = status;
50
+ this.body = body;
51
+ }
52
+ };
53
+ var AuthenticationError = class extends ApiError {
54
+ };
55
+ var RateLimitError = class extends ApiError {
56
+ };
57
+ var InvalidRequestError = class extends ApiError {
58
+ };
59
+ function messageFor(status, body) {
60
+ const error = body.error;
61
+ if (error && typeof error === "object" && "message" in error) {
62
+ const message = error.message;
63
+ if (typeof message === "string") {
64
+ return message;
65
+ }
66
+ }
67
+ return `HTTP ${status}`;
68
+ }
69
+ function mapError(status, body) {
70
+ const message = messageFor(status, body);
71
+ if (status === 401 || status === 403) {
72
+ return new AuthenticationError(message, status, body);
73
+ }
74
+ if (status === 429) {
75
+ return new RateLimitError(message, status, body);
76
+ }
77
+ if (status >= 400 && status < 500) {
78
+ return new InvalidRequestError(message, status, body);
79
+ }
80
+ return new ApiError(message, status, body);
81
+ }
82
+
83
+ // src/streaming/sse.ts
84
+ var DONE_SENTINEL = "[DONE]";
85
+ function parseSseChunk(buffer, onEvent) {
86
+ let rest = buffer;
87
+ let newlineIndex = rest.indexOf("\n");
88
+ while (newlineIndex !== -1) {
89
+ const line = rest.slice(0, newlineIndex).replace(/\r$/, "");
90
+ rest = rest.slice(newlineIndex + 1);
91
+ const event = parseSseLine(line);
92
+ if (event !== null) {
93
+ onEvent(event);
94
+ }
95
+ newlineIndex = rest.indexOf("\n");
96
+ }
97
+ return rest;
98
+ }
99
+ function parseSseLine(line) {
100
+ if (!line.startsWith("data:")) {
101
+ return null;
102
+ }
103
+ const data = line.slice(5).trim();
104
+ if (data === "" || data === DONE_SENTINEL) {
105
+ return null;
106
+ }
107
+ return JSON.parse(data);
108
+ }
109
+
110
+ // src/client/config.ts
111
+ function resolveConfig(config) {
112
+ return {
113
+ apiKey: config.apiKey,
114
+ baseUrl: config.baseUrl ?? "https://api.akumi.cloud/v1",
115
+ maxRetries: config.maxRetries ?? 2,
116
+ retryOn: config.retryOn ?? [429, 500, 502, 503, 504]
117
+ };
118
+ }
119
+
120
+ // src/client/transport.ts
121
+ var Transport = class {
122
+ config;
123
+ constructor(config) {
124
+ this.config = resolveConfig(config);
125
+ }
126
+ async request(method, path, query, body) {
127
+ const response = await this.dispatch(method, path, query, body, false);
128
+ const text = await response.text();
129
+ if (text === "") {
130
+ return {};
131
+ }
132
+ const decoded = JSON.parse(text);
133
+ return typeof decoded === "object" && decoded !== null ? decoded : {};
134
+ }
135
+ async *stream(method, path, body) {
136
+ const response = await this.dispatch(method, path, null, body, true);
137
+ const stream = response.body;
138
+ if (stream === null) {
139
+ return;
140
+ }
141
+ const reader = stream.getReader();
142
+ const decoder = new TextDecoder();
143
+ const events = [];
144
+ let buffer = "";
145
+ try {
146
+ for (; ; ) {
147
+ const { done, value } = await reader.read();
148
+ if (done) {
149
+ break;
150
+ }
151
+ buffer += decoder.decode(value, { stream: true });
152
+ buffer = parseSseChunk(buffer, (event2) => events.push(event2));
153
+ while (events.length > 0) {
154
+ yield events.shift();
155
+ }
156
+ }
157
+ } finally {
158
+ reader.releaseLock();
159
+ }
160
+ const event = parseSseLine(buffer.replace(/\r$/, ""));
161
+ if (event !== null) {
162
+ yield event;
163
+ }
164
+ }
165
+ async dispatch(method, path, query, body, stream) {
166
+ let url = this.config.baseUrl.replace(/\/$/, "") + path;
167
+ if (query !== null) {
168
+ const search = new URLSearchParams();
169
+ for (const [key, value] of Object.entries(query)) {
170
+ if (value !== null && value !== void 0) {
171
+ search.append(key, String(value));
172
+ }
173
+ }
174
+ const queryString = search.toString();
175
+ if (queryString !== "") {
176
+ url += `?${queryString}`;
177
+ }
178
+ }
179
+ const headers = {
180
+ Authorization: `Bearer ${this.config.apiKey}`,
181
+ Accept: stream ? "text/event-stream" : "application/json"
182
+ };
183
+ const init = { method, headers };
184
+ if (body !== null) {
185
+ headers["Content-Type"] = "application/json";
186
+ init.body = JSON.stringify(body);
187
+ }
188
+ let attempt = 0;
189
+ for (; ; ) {
190
+ const response = await fetch(url, init);
191
+ if (response.status < 400) {
192
+ return response;
193
+ }
194
+ const shouldRetry = attempt < this.config.maxRetries && this.config.retryOn.includes(response.status);
195
+ if (shouldRetry) {
196
+ attempt += 1;
197
+ await delay(250 * 2 ** (attempt - 1));
198
+ continue;
199
+ }
200
+ const text = await response.text();
201
+ let parsed = {};
202
+ if (text !== "") {
203
+ const decoded = safeJsonParse(text);
204
+ if (typeof decoded === "object" && decoded !== null) {
205
+ parsed = decoded;
206
+ }
207
+ }
208
+ throw mapError(response.status, parsed);
209
+ }
210
+ }
211
+ };
212
+ function delay(ms) {
213
+ return new Promise((resolve) => setTimeout(resolve, ms));
214
+ }
215
+ function safeJsonParse(text) {
216
+ try {
217
+ return JSON.parse(text);
218
+ } catch {
219
+ return null;
220
+ }
221
+ }
222
+
223
+ // src/resources/recall.ts
224
+ var RecallResource = class {
225
+ constructor(transport) {
226
+ this.transport = transport;
227
+ }
228
+ transport;
229
+ async listThreads(query = {}) {
230
+ return this.transport.request("GET", "/recall/threads", query, null);
231
+ }
232
+ async createThread() {
233
+ return this.transport.request("POST", "/recall/threads", null, null);
234
+ }
235
+ async getThread(thread) {
236
+ return this.transport.request("GET", `/recall/threads/${thread}`, null, null);
237
+ }
238
+ async deleteThread(thread) {
239
+ return this.transport.request("DELETE", `/recall/threads/${thread}`, null, null);
240
+ }
241
+ async search(params = {}) {
242
+ return this.transport.request("POST", "/recall/search", null, params);
243
+ }
244
+ async searchFacts(params = {}) {
245
+ return this.transport.request("POST", "/recall/facts/search", null, params);
246
+ }
247
+ async listFacts(query = {}) {
248
+ return this.transport.request("GET", "/recall/facts", query, null);
249
+ }
250
+ async rememberFact(params = {}) {
251
+ return this.transport.request("POST", "/recall/facts", null, params);
252
+ }
253
+ async forgetFact(id) {
254
+ return this.transport.request("DELETE", `/recall/facts/${id}`, null, null);
255
+ }
256
+ async export(query = {}) {
257
+ return this.transport.request("GET", "/recall/export", query, null);
258
+ }
259
+ async erase() {
260
+ return this.transport.request("DELETE", "/recall", null, null);
261
+ }
262
+ async searchDocuments(params = {}) {
263
+ return this.transport.request("POST", "/recall/documents/search", null, params);
264
+ }
265
+ async listDocuments(query = {}) {
266
+ return this.transport.request("GET", "/recall/documents", query, null);
267
+ }
268
+ async ingestDocument(params = {}) {
269
+ return this.transport.request("POST", "/recall/documents", null, params);
270
+ }
271
+ async getDocument(document) {
272
+ return this.transport.request("GET", `/recall/documents/${document}`, null, null);
273
+ }
274
+ async deleteDocument(document) {
275
+ return this.transport.request("DELETE", `/recall/documents/${document}`, null, null);
276
+ }
277
+ async listCollections(query = {}) {
278
+ return this.transport.request("GET", "/recall/collections", query, null);
279
+ }
280
+ async createCollection(params = {}) {
281
+ return this.transport.request("POST", "/recall/collections", null, params);
282
+ }
283
+ async getCollection(slug) {
284
+ return this.transport.request("GET", `/recall/collections/${slug}`, null, null);
285
+ }
286
+ async deleteCollection(slug) {
287
+ return this.transport.request("DELETE", `/recall/collections/${slug}`, null, null);
288
+ }
289
+ async updateCollection(slug, params = {}) {
290
+ return this.transport.request("PATCH", `/recall/collections/${slug}`, null, params);
291
+ }
292
+ };
293
+
294
+ // src/resources/auditLogs.ts
295
+ var AuditLogsResource = class {
296
+ constructor(transport) {
297
+ this.transport = transport;
298
+ }
299
+ transport;
300
+ async list(query = {}) {
301
+ return this.transport.request("GET", "/audit-logs", query, null);
302
+ }
303
+ async get(uuid) {
304
+ return this.transport.request("GET", `/audit-logs/${uuid}`, null, null);
305
+ }
306
+ };
307
+
308
+ // src/resources/chat.ts
309
+ var ChatResource = class {
310
+ constructor(transport) {
311
+ this.transport = transport;
312
+ }
313
+ transport;
314
+ async create(params = {}) {
315
+ return this.transport.request("POST", "/chat/completions", null, params);
316
+ }
317
+ async *createStreamed(params = {}) {
318
+ yield* this.transport.stream("POST", "/chat/completions", params);
319
+ }
320
+ };
321
+
322
+ // src/resources/embeddings.ts
323
+ var EmbeddingsResource = class {
324
+ constructor(transport) {
325
+ this.transport = transport;
326
+ }
327
+ transport;
328
+ async create(params = {}) {
329
+ return this.transport.request("POST", "/embeddings", null, params);
330
+ }
331
+ };
332
+
333
+ // src/resources/models.ts
334
+ var ModelsResource = class {
335
+ constructor(transport) {
336
+ this.transport = transport;
337
+ }
338
+ transport;
339
+ async list() {
340
+ return this.transport.request("GET", "/models", null, null);
341
+ }
342
+ };
343
+
344
+ // src/client.ts
345
+ var Akumi = class _Akumi {
346
+ transport;
347
+ recall;
348
+ auditLogs;
349
+ chat;
350
+ embeddings;
351
+ models;
352
+ constructor(config) {
353
+ this.transport = new Transport(config);
354
+ this.recall = new RecallResource(this.transport);
355
+ this.auditLogs = new AuditLogsResource(this.transport);
356
+ this.chat = new ChatResource(this.transport);
357
+ this.embeddings = new EmbeddingsResource(this.transport);
358
+ this.models = new ModelsResource(this.transport);
359
+ }
360
+ static fromApiKey(apiKey) {
361
+ return new _Akumi({ apiKey });
362
+ }
363
+ };
364
+ // Annotate the CommonJS export names for ESM import in node:
365
+ 0 && (module.exports = {
366
+ Akumi,
367
+ AkumiError,
368
+ ApiError,
369
+ AuditLogsResource,
370
+ AuthenticationError,
371
+ ChatResource,
372
+ EmbeddingsResource,
373
+ InvalidRequestError,
374
+ ModelsResource,
375
+ RateLimitError,
376
+ RecallResource
377
+ });
@@ -0,0 +1,187 @@
1
+ interface ClientConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ maxRetries?: number;
5
+ retryOn?: number[];
6
+ }
7
+
8
+ /**
9
+ * Builds and sends HTTP requests for the SDK: bearer auth, JSON encoding,
10
+ * status-to-error mapping, retries with backoff, and incremental SSE reads.
11
+ * The API key is sent only on the Authorization header and never logged.
12
+ */
13
+ declare class Transport {
14
+ private readonly config;
15
+ constructor(config: ClientConfig);
16
+ request(method: string, path: string, query: Record<string, unknown> | null, body: Record<string, unknown> | null): Promise<Record<string, unknown>>;
17
+ stream(method: string, path: string, body: Record<string, unknown> | null): AsyncGenerator<Record<string, unknown>>;
18
+ private dispatch;
19
+ }
20
+
21
+ declare class RecallResource {
22
+ private readonly transport;
23
+ constructor(transport: Transport);
24
+ listThreads(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
25
+ createThread(): Promise<Record<string, unknown>>;
26
+ getThread(thread: string): Promise<Record<string, unknown>>;
27
+ deleteThread(thread: string): Promise<Record<string, unknown>>;
28
+ search(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
29
+ searchFacts(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
30
+ listFacts(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
31
+ rememberFact(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
32
+ forgetFact(id: string): Promise<Record<string, unknown>>;
33
+ export(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
34
+ erase(): Promise<Record<string, unknown>>;
35
+ searchDocuments(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
36
+ listDocuments(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
37
+ ingestDocument(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
38
+ getDocument(document: string): Promise<Record<string, unknown>>;
39
+ deleteDocument(document: string): Promise<Record<string, unknown>>;
40
+ listCollections(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
41
+ createCollection(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
42
+ getCollection(slug: string): Promise<Record<string, unknown>>;
43
+ deleteCollection(slug: string): Promise<Record<string, unknown>>;
44
+ updateCollection(slug: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
45
+ }
46
+
47
+ declare class AuditLogsResource {
48
+ private readonly transport;
49
+ constructor(transport: Transport);
50
+ list(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
51
+ get(uuid: string): Promise<Record<string, unknown>>;
52
+ }
53
+
54
+ declare class ChatResource {
55
+ private readonly transport;
56
+ constructor(transport: Transport);
57
+ create(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
58
+ createStreamed(params?: Record<string, unknown>): AsyncGenerator<Record<string, unknown>>;
59
+ }
60
+
61
+ declare class EmbeddingsResource {
62
+ private readonly transport;
63
+ constructor(transport: Transport);
64
+ create(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
65
+ }
66
+
67
+ declare class ModelsResource {
68
+ private readonly transport;
69
+ constructor(transport: Transport);
70
+ list(): Promise<Record<string, unknown>>;
71
+ }
72
+
73
+ declare class Akumi {
74
+ private readonly transport;
75
+ readonly recall: RecallResource;
76
+ readonly auditLogs: AuditLogsResource;
77
+ readonly chat: ChatResource;
78
+ readonly embeddings: EmbeddingsResource;
79
+ readonly models: ModelsResource;
80
+ constructor(config: ClientConfig);
81
+ static fromApiKey(apiKey: string): Akumi;
82
+ }
83
+
84
+ declare class AkumiError extends Error {
85
+ constructor(message: string);
86
+ }
87
+ declare class ApiError extends AkumiError {
88
+ readonly status: number;
89
+ readonly body: Record<string, unknown>;
90
+ constructor(message: string, status: number, body?: Record<string, unknown>);
91
+ }
92
+ declare class AuthenticationError extends ApiError {
93
+ }
94
+ declare class RateLimitError extends ApiError {
95
+ }
96
+ declare class InvalidRequestError extends ApiError {
97
+ }
98
+
99
+ interface AuditLogApiResource {
100
+ id: string;
101
+ component: string;
102
+ action: string;
103
+ actorId: number | null;
104
+ ipAddress: string | null;
105
+ userAgent: string | null;
106
+ target: unknown | null;
107
+ metadata: unknown[] | null;
108
+ createdAt: string;
109
+ }
110
+
111
+ interface ChatCompletionsRequest {
112
+ model: string;
113
+ messages: unknown[];
114
+ temperature?: number | null;
115
+ max_tokens?: number | null;
116
+ stream?: boolean | null;
117
+ firewall?: boolean | null;
118
+ rag?: string | null;
119
+ user?: string | null;
120
+ thread?: string | null;
121
+ top_p?: number | null;
122
+ presence_penalty?: number | null;
123
+ frequency_penalty?: number | null;
124
+ n?: number | null;
125
+ seed?: number | null;
126
+ logprobs?: boolean | null;
127
+ top_logprobs?: number | null;
128
+ max_completion_tokens?: number | null;
129
+ tool_choice?: string | null;
130
+ parallel_tool_calls?: boolean | null;
131
+ cache?: boolean | null;
132
+ stop?: string[] | null;
133
+ logit_bias?: number[] | null;
134
+ response_format?: unknown;
135
+ tools?: unknown[] | null;
136
+ }
137
+
138
+ interface EmbeddingsRequest {
139
+ model: string;
140
+ input: string[];
141
+ encoding_format?: string | null;
142
+ dimensions?: number | null;
143
+ user?: string | null;
144
+ }
145
+
146
+ interface IngestDocumentRequest {
147
+ title: string;
148
+ text: string;
149
+ source?: string | null;
150
+ collection?: string | null;
151
+ }
152
+
153
+ interface RememberFactRequest {
154
+ content: string;
155
+ user_ref: string;
156
+ }
157
+
158
+ interface SearchDocumentsRequest {
159
+ query: string;
160
+ collection: string;
161
+ user_ref?: string | null;
162
+ limit?: number | null;
163
+ }
164
+
165
+ interface SearchFactsRequest {
166
+ query: string;
167
+ user_ref?: string | null;
168
+ limit?: number | null;
169
+ }
170
+
171
+ interface SearchRequest {
172
+ query: string;
173
+ user_ref?: string | null;
174
+ limit?: number | null;
175
+ }
176
+
177
+ interface StoreCollectionRequest {
178
+ name: string;
179
+ }
180
+
181
+ interface ThreadMessageViewModel {
182
+ }
183
+
184
+ interface ThreadViewModel {
185
+ }
186
+
187
+ export { Akumi, AkumiError, ApiError, type AuditLogApiResource, AuditLogsResource, AuthenticationError, type ChatCompletionsRequest, ChatResource, type ClientConfig, type EmbeddingsRequest, EmbeddingsResource, type IngestDocumentRequest, InvalidRequestError, ModelsResource, RateLimitError, RecallResource, type RememberFactRequest, type SearchDocumentsRequest, type SearchFactsRequest, type SearchRequest, type StoreCollectionRequest, type ThreadMessageViewModel, type ThreadViewModel };
@@ -0,0 +1,187 @@
1
+ interface ClientConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ maxRetries?: number;
5
+ retryOn?: number[];
6
+ }
7
+
8
+ /**
9
+ * Builds and sends HTTP requests for the SDK: bearer auth, JSON encoding,
10
+ * status-to-error mapping, retries with backoff, and incremental SSE reads.
11
+ * The API key is sent only on the Authorization header and never logged.
12
+ */
13
+ declare class Transport {
14
+ private readonly config;
15
+ constructor(config: ClientConfig);
16
+ request(method: string, path: string, query: Record<string, unknown> | null, body: Record<string, unknown> | null): Promise<Record<string, unknown>>;
17
+ stream(method: string, path: string, body: Record<string, unknown> | null): AsyncGenerator<Record<string, unknown>>;
18
+ private dispatch;
19
+ }
20
+
21
+ declare class RecallResource {
22
+ private readonly transport;
23
+ constructor(transport: Transport);
24
+ listThreads(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
25
+ createThread(): Promise<Record<string, unknown>>;
26
+ getThread(thread: string): Promise<Record<string, unknown>>;
27
+ deleteThread(thread: string): Promise<Record<string, unknown>>;
28
+ search(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
29
+ searchFacts(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
30
+ listFacts(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
31
+ rememberFact(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
32
+ forgetFact(id: string): Promise<Record<string, unknown>>;
33
+ export(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
34
+ erase(): Promise<Record<string, unknown>>;
35
+ searchDocuments(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
36
+ listDocuments(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
37
+ ingestDocument(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
38
+ getDocument(document: string): Promise<Record<string, unknown>>;
39
+ deleteDocument(document: string): Promise<Record<string, unknown>>;
40
+ listCollections(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
41
+ createCollection(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
42
+ getCollection(slug: string): Promise<Record<string, unknown>>;
43
+ deleteCollection(slug: string): Promise<Record<string, unknown>>;
44
+ updateCollection(slug: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
45
+ }
46
+
47
+ declare class AuditLogsResource {
48
+ private readonly transport;
49
+ constructor(transport: Transport);
50
+ list(query?: Record<string, unknown>): Promise<Record<string, unknown>>;
51
+ get(uuid: string): Promise<Record<string, unknown>>;
52
+ }
53
+
54
+ declare class ChatResource {
55
+ private readonly transport;
56
+ constructor(transport: Transport);
57
+ create(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
58
+ createStreamed(params?: Record<string, unknown>): AsyncGenerator<Record<string, unknown>>;
59
+ }
60
+
61
+ declare class EmbeddingsResource {
62
+ private readonly transport;
63
+ constructor(transport: Transport);
64
+ create(params?: Record<string, unknown>): Promise<Record<string, unknown>>;
65
+ }
66
+
67
+ declare class ModelsResource {
68
+ private readonly transport;
69
+ constructor(transport: Transport);
70
+ list(): Promise<Record<string, unknown>>;
71
+ }
72
+
73
+ declare class Akumi {
74
+ private readonly transport;
75
+ readonly recall: RecallResource;
76
+ readonly auditLogs: AuditLogsResource;
77
+ readonly chat: ChatResource;
78
+ readonly embeddings: EmbeddingsResource;
79
+ readonly models: ModelsResource;
80
+ constructor(config: ClientConfig);
81
+ static fromApiKey(apiKey: string): Akumi;
82
+ }
83
+
84
+ declare class AkumiError extends Error {
85
+ constructor(message: string);
86
+ }
87
+ declare class ApiError extends AkumiError {
88
+ readonly status: number;
89
+ readonly body: Record<string, unknown>;
90
+ constructor(message: string, status: number, body?: Record<string, unknown>);
91
+ }
92
+ declare class AuthenticationError extends ApiError {
93
+ }
94
+ declare class RateLimitError extends ApiError {
95
+ }
96
+ declare class InvalidRequestError extends ApiError {
97
+ }
98
+
99
+ interface AuditLogApiResource {
100
+ id: string;
101
+ component: string;
102
+ action: string;
103
+ actorId: number | null;
104
+ ipAddress: string | null;
105
+ userAgent: string | null;
106
+ target: unknown | null;
107
+ metadata: unknown[] | null;
108
+ createdAt: string;
109
+ }
110
+
111
+ interface ChatCompletionsRequest {
112
+ model: string;
113
+ messages: unknown[];
114
+ temperature?: number | null;
115
+ max_tokens?: number | null;
116
+ stream?: boolean | null;
117
+ firewall?: boolean | null;
118
+ rag?: string | null;
119
+ user?: string | null;
120
+ thread?: string | null;
121
+ top_p?: number | null;
122
+ presence_penalty?: number | null;
123
+ frequency_penalty?: number | null;
124
+ n?: number | null;
125
+ seed?: number | null;
126
+ logprobs?: boolean | null;
127
+ top_logprobs?: number | null;
128
+ max_completion_tokens?: number | null;
129
+ tool_choice?: string | null;
130
+ parallel_tool_calls?: boolean | null;
131
+ cache?: boolean | null;
132
+ stop?: string[] | null;
133
+ logit_bias?: number[] | null;
134
+ response_format?: unknown;
135
+ tools?: unknown[] | null;
136
+ }
137
+
138
+ interface EmbeddingsRequest {
139
+ model: string;
140
+ input: string[];
141
+ encoding_format?: string | null;
142
+ dimensions?: number | null;
143
+ user?: string | null;
144
+ }
145
+
146
+ interface IngestDocumentRequest {
147
+ title: string;
148
+ text: string;
149
+ source?: string | null;
150
+ collection?: string | null;
151
+ }
152
+
153
+ interface RememberFactRequest {
154
+ content: string;
155
+ user_ref: string;
156
+ }
157
+
158
+ interface SearchDocumentsRequest {
159
+ query: string;
160
+ collection: string;
161
+ user_ref?: string | null;
162
+ limit?: number | null;
163
+ }
164
+
165
+ interface SearchFactsRequest {
166
+ query: string;
167
+ user_ref?: string | null;
168
+ limit?: number | null;
169
+ }
170
+
171
+ interface SearchRequest {
172
+ query: string;
173
+ user_ref?: string | null;
174
+ limit?: number | null;
175
+ }
176
+
177
+ interface StoreCollectionRequest {
178
+ name: string;
179
+ }
180
+
181
+ interface ThreadMessageViewModel {
182
+ }
183
+
184
+ interface ThreadViewModel {
185
+ }
186
+
187
+ export { Akumi, AkumiError, ApiError, type AuditLogApiResource, AuditLogsResource, AuthenticationError, type ChatCompletionsRequest, ChatResource, type ClientConfig, type EmbeddingsRequest, EmbeddingsResource, type IngestDocumentRequest, InvalidRequestError, ModelsResource, RateLimitError, RecallResource, type RememberFactRequest, type SearchDocumentsRequest, type SearchFactsRequest, type SearchRequest, type StoreCollectionRequest, type ThreadMessageViewModel, type ThreadViewModel };
package/dist/index.js ADDED
@@ -0,0 +1,340 @@
1
+ // src/errors.ts
2
+ var AkumiError = class extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = new.target.name;
6
+ }
7
+ };
8
+ var ApiError = class extends AkumiError {
9
+ status;
10
+ body;
11
+ constructor(message, status, body = {}) {
12
+ super(message);
13
+ this.status = status;
14
+ this.body = body;
15
+ }
16
+ };
17
+ var AuthenticationError = class extends ApiError {
18
+ };
19
+ var RateLimitError = class extends ApiError {
20
+ };
21
+ var InvalidRequestError = class extends ApiError {
22
+ };
23
+ function messageFor(status, body) {
24
+ const error = body.error;
25
+ if (error && typeof error === "object" && "message" in error) {
26
+ const message = error.message;
27
+ if (typeof message === "string") {
28
+ return message;
29
+ }
30
+ }
31
+ return `HTTP ${status}`;
32
+ }
33
+ function mapError(status, body) {
34
+ const message = messageFor(status, body);
35
+ if (status === 401 || status === 403) {
36
+ return new AuthenticationError(message, status, body);
37
+ }
38
+ if (status === 429) {
39
+ return new RateLimitError(message, status, body);
40
+ }
41
+ if (status >= 400 && status < 500) {
42
+ return new InvalidRequestError(message, status, body);
43
+ }
44
+ return new ApiError(message, status, body);
45
+ }
46
+
47
+ // src/streaming/sse.ts
48
+ var DONE_SENTINEL = "[DONE]";
49
+ function parseSseChunk(buffer, onEvent) {
50
+ let rest = buffer;
51
+ let newlineIndex = rest.indexOf("\n");
52
+ while (newlineIndex !== -1) {
53
+ const line = rest.slice(0, newlineIndex).replace(/\r$/, "");
54
+ rest = rest.slice(newlineIndex + 1);
55
+ const event = parseSseLine(line);
56
+ if (event !== null) {
57
+ onEvent(event);
58
+ }
59
+ newlineIndex = rest.indexOf("\n");
60
+ }
61
+ return rest;
62
+ }
63
+ function parseSseLine(line) {
64
+ if (!line.startsWith("data:")) {
65
+ return null;
66
+ }
67
+ const data = line.slice(5).trim();
68
+ if (data === "" || data === DONE_SENTINEL) {
69
+ return null;
70
+ }
71
+ return JSON.parse(data);
72
+ }
73
+
74
+ // src/client/config.ts
75
+ function resolveConfig(config) {
76
+ return {
77
+ apiKey: config.apiKey,
78
+ baseUrl: config.baseUrl ?? "https://api.akumi.cloud/v1",
79
+ maxRetries: config.maxRetries ?? 2,
80
+ retryOn: config.retryOn ?? [429, 500, 502, 503, 504]
81
+ };
82
+ }
83
+
84
+ // src/client/transport.ts
85
+ var Transport = class {
86
+ config;
87
+ constructor(config) {
88
+ this.config = resolveConfig(config);
89
+ }
90
+ async request(method, path, query, body) {
91
+ const response = await this.dispatch(method, path, query, body, false);
92
+ const text = await response.text();
93
+ if (text === "") {
94
+ return {};
95
+ }
96
+ const decoded = JSON.parse(text);
97
+ return typeof decoded === "object" && decoded !== null ? decoded : {};
98
+ }
99
+ async *stream(method, path, body) {
100
+ const response = await this.dispatch(method, path, null, body, true);
101
+ const stream = response.body;
102
+ if (stream === null) {
103
+ return;
104
+ }
105
+ const reader = stream.getReader();
106
+ const decoder = new TextDecoder();
107
+ const events = [];
108
+ let buffer = "";
109
+ try {
110
+ for (; ; ) {
111
+ const { done, value } = await reader.read();
112
+ if (done) {
113
+ break;
114
+ }
115
+ buffer += decoder.decode(value, { stream: true });
116
+ buffer = parseSseChunk(buffer, (event2) => events.push(event2));
117
+ while (events.length > 0) {
118
+ yield events.shift();
119
+ }
120
+ }
121
+ } finally {
122
+ reader.releaseLock();
123
+ }
124
+ const event = parseSseLine(buffer.replace(/\r$/, ""));
125
+ if (event !== null) {
126
+ yield event;
127
+ }
128
+ }
129
+ async dispatch(method, path, query, body, stream) {
130
+ let url = this.config.baseUrl.replace(/\/$/, "") + path;
131
+ if (query !== null) {
132
+ const search = new URLSearchParams();
133
+ for (const [key, value] of Object.entries(query)) {
134
+ if (value !== null && value !== void 0) {
135
+ search.append(key, String(value));
136
+ }
137
+ }
138
+ const queryString = search.toString();
139
+ if (queryString !== "") {
140
+ url += `?${queryString}`;
141
+ }
142
+ }
143
+ const headers = {
144
+ Authorization: `Bearer ${this.config.apiKey}`,
145
+ Accept: stream ? "text/event-stream" : "application/json"
146
+ };
147
+ const init = { method, headers };
148
+ if (body !== null) {
149
+ headers["Content-Type"] = "application/json";
150
+ init.body = JSON.stringify(body);
151
+ }
152
+ let attempt = 0;
153
+ for (; ; ) {
154
+ const response = await fetch(url, init);
155
+ if (response.status < 400) {
156
+ return response;
157
+ }
158
+ const shouldRetry = attempt < this.config.maxRetries && this.config.retryOn.includes(response.status);
159
+ if (shouldRetry) {
160
+ attempt += 1;
161
+ await delay(250 * 2 ** (attempt - 1));
162
+ continue;
163
+ }
164
+ const text = await response.text();
165
+ let parsed = {};
166
+ if (text !== "") {
167
+ const decoded = safeJsonParse(text);
168
+ if (typeof decoded === "object" && decoded !== null) {
169
+ parsed = decoded;
170
+ }
171
+ }
172
+ throw mapError(response.status, parsed);
173
+ }
174
+ }
175
+ };
176
+ function delay(ms) {
177
+ return new Promise((resolve) => setTimeout(resolve, ms));
178
+ }
179
+ function safeJsonParse(text) {
180
+ try {
181
+ return JSON.parse(text);
182
+ } catch {
183
+ return null;
184
+ }
185
+ }
186
+
187
+ // src/resources/recall.ts
188
+ var RecallResource = class {
189
+ constructor(transport) {
190
+ this.transport = transport;
191
+ }
192
+ transport;
193
+ async listThreads(query = {}) {
194
+ return this.transport.request("GET", "/recall/threads", query, null);
195
+ }
196
+ async createThread() {
197
+ return this.transport.request("POST", "/recall/threads", null, null);
198
+ }
199
+ async getThread(thread) {
200
+ return this.transport.request("GET", `/recall/threads/${thread}`, null, null);
201
+ }
202
+ async deleteThread(thread) {
203
+ return this.transport.request("DELETE", `/recall/threads/${thread}`, null, null);
204
+ }
205
+ async search(params = {}) {
206
+ return this.transport.request("POST", "/recall/search", null, params);
207
+ }
208
+ async searchFacts(params = {}) {
209
+ return this.transport.request("POST", "/recall/facts/search", null, params);
210
+ }
211
+ async listFacts(query = {}) {
212
+ return this.transport.request("GET", "/recall/facts", query, null);
213
+ }
214
+ async rememberFact(params = {}) {
215
+ return this.transport.request("POST", "/recall/facts", null, params);
216
+ }
217
+ async forgetFact(id) {
218
+ return this.transport.request("DELETE", `/recall/facts/${id}`, null, null);
219
+ }
220
+ async export(query = {}) {
221
+ return this.transport.request("GET", "/recall/export", query, null);
222
+ }
223
+ async erase() {
224
+ return this.transport.request("DELETE", "/recall", null, null);
225
+ }
226
+ async searchDocuments(params = {}) {
227
+ return this.transport.request("POST", "/recall/documents/search", null, params);
228
+ }
229
+ async listDocuments(query = {}) {
230
+ return this.transport.request("GET", "/recall/documents", query, null);
231
+ }
232
+ async ingestDocument(params = {}) {
233
+ return this.transport.request("POST", "/recall/documents", null, params);
234
+ }
235
+ async getDocument(document) {
236
+ return this.transport.request("GET", `/recall/documents/${document}`, null, null);
237
+ }
238
+ async deleteDocument(document) {
239
+ return this.transport.request("DELETE", `/recall/documents/${document}`, null, null);
240
+ }
241
+ async listCollections(query = {}) {
242
+ return this.transport.request("GET", "/recall/collections", query, null);
243
+ }
244
+ async createCollection(params = {}) {
245
+ return this.transport.request("POST", "/recall/collections", null, params);
246
+ }
247
+ async getCollection(slug) {
248
+ return this.transport.request("GET", `/recall/collections/${slug}`, null, null);
249
+ }
250
+ async deleteCollection(slug) {
251
+ return this.transport.request("DELETE", `/recall/collections/${slug}`, null, null);
252
+ }
253
+ async updateCollection(slug, params = {}) {
254
+ return this.transport.request("PATCH", `/recall/collections/${slug}`, null, params);
255
+ }
256
+ };
257
+
258
+ // src/resources/auditLogs.ts
259
+ var AuditLogsResource = class {
260
+ constructor(transport) {
261
+ this.transport = transport;
262
+ }
263
+ transport;
264
+ async list(query = {}) {
265
+ return this.transport.request("GET", "/audit-logs", query, null);
266
+ }
267
+ async get(uuid) {
268
+ return this.transport.request("GET", `/audit-logs/${uuid}`, null, null);
269
+ }
270
+ };
271
+
272
+ // src/resources/chat.ts
273
+ var ChatResource = class {
274
+ constructor(transport) {
275
+ this.transport = transport;
276
+ }
277
+ transport;
278
+ async create(params = {}) {
279
+ return this.transport.request("POST", "/chat/completions", null, params);
280
+ }
281
+ async *createStreamed(params = {}) {
282
+ yield* this.transport.stream("POST", "/chat/completions", params);
283
+ }
284
+ };
285
+
286
+ // src/resources/embeddings.ts
287
+ var EmbeddingsResource = class {
288
+ constructor(transport) {
289
+ this.transport = transport;
290
+ }
291
+ transport;
292
+ async create(params = {}) {
293
+ return this.transport.request("POST", "/embeddings", null, params);
294
+ }
295
+ };
296
+
297
+ // src/resources/models.ts
298
+ var ModelsResource = class {
299
+ constructor(transport) {
300
+ this.transport = transport;
301
+ }
302
+ transport;
303
+ async list() {
304
+ return this.transport.request("GET", "/models", null, null);
305
+ }
306
+ };
307
+
308
+ // src/client.ts
309
+ var Akumi = class _Akumi {
310
+ transport;
311
+ recall;
312
+ auditLogs;
313
+ chat;
314
+ embeddings;
315
+ models;
316
+ constructor(config) {
317
+ this.transport = new Transport(config);
318
+ this.recall = new RecallResource(this.transport);
319
+ this.auditLogs = new AuditLogsResource(this.transport);
320
+ this.chat = new ChatResource(this.transport);
321
+ this.embeddings = new EmbeddingsResource(this.transport);
322
+ this.models = new ModelsResource(this.transport);
323
+ }
324
+ static fromApiKey(apiKey) {
325
+ return new _Akumi({ apiKey });
326
+ }
327
+ };
328
+ export {
329
+ Akumi,
330
+ AkumiError,
331
+ ApiError,
332
+ AuditLogsResource,
333
+ AuthenticationError,
334
+ ChatResource,
335
+ EmbeddingsResource,
336
+ InvalidRequestError,
337
+ ModelsResource,
338
+ RateLimitError,
339
+ RecallResource
340
+ };
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@akumi/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Official TypeScript SDK for the Akumi EU-sovereign inference API.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "typecheck": "tsc --noEmit"
23
+ },
24
+ "devDependencies": {
25
+ "tsup": "^8.3.0",
26
+ "typescript": "^5.6.0"
27
+ },
28
+ "engines": {
29
+ "node": ">=18"
30
+ }
31
+ }