bluekiwi 0.3.0 → 0.3.1

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.
@@ -0,0 +1,6 @@
1
+ export declare class BlueKiwiClient {
2
+ private baseUrl;
3
+ private apiKey;
4
+ constructor(baseUrl: string, apiKey: string);
5
+ request<T>(method: string, path: string, body?: unknown): Promise<T>;
6
+ }
@@ -0,0 +1,67 @@
1
+ import {
2
+ BlueKiwiAuthError,
3
+ BlueKiwiApiError,
4
+ BlueKiwiNetworkError,
5
+ } from "./errors.js";
6
+ const RETRY_DELAYS_MS = [100, 500, 2000];
7
+ export class BlueKiwiClient {
8
+ baseUrl;
9
+ apiKey;
10
+ constructor(baseUrl, apiKey) {
11
+ this.baseUrl = baseUrl;
12
+ this.apiKey = apiKey;
13
+ if (!baseUrl) throw new Error("BlueKiwiClient: baseUrl is required");
14
+ if (!apiKey) throw new Error("BlueKiwiClient: apiKey is required");
15
+ }
16
+ async request(method, path, body) {
17
+ const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
18
+ const init = {
19
+ method,
20
+ headers: {
21
+ "Content-Type": "application/json",
22
+ Authorization: `Bearer ${this.apiKey}`,
23
+ },
24
+ body: body === undefined ? undefined : JSON.stringify(body),
25
+ };
26
+ let lastError;
27
+ for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {
28
+ try {
29
+ const res = await fetch(url, init);
30
+ if (res.status === 401) {
31
+ throw new BlueKiwiAuthError();
32
+ }
33
+ if (!res.ok) {
34
+ const text = await res.text().catch(() => "");
35
+ if (res.status >= 500 && attempt < RETRY_DELAYS_MS.length) {
36
+ lastError = new BlueKiwiApiError(res.status, text);
37
+ await sleep(RETRY_DELAYS_MS[attempt]);
38
+ continue;
39
+ }
40
+ throw new BlueKiwiApiError(res.status, text);
41
+ }
42
+ const text = await res.text();
43
+ return text ? JSON.parse(text) : null;
44
+ } catch (err) {
45
+ if (
46
+ err instanceof BlueKiwiAuthError ||
47
+ err instanceof BlueKiwiApiError
48
+ ) {
49
+ throw err;
50
+ }
51
+ lastError = err;
52
+ if (attempt < RETRY_DELAYS_MS.length) {
53
+ await sleep(RETRY_DELAYS_MS[attempt]);
54
+ continue;
55
+ }
56
+ throw new BlueKiwiNetworkError(
57
+ `Failed to reach ${url} after ${RETRY_DELAYS_MS.length + 1} attempts`,
58
+ err,
59
+ );
60
+ }
61
+ }
62
+ throw new BlueKiwiNetworkError("Unreachable", lastError);
63
+ }
64
+ }
65
+ function sleep(ms) {
66
+ return new Promise((r) => setTimeout(r, ms));
67
+ }
@@ -0,0 +1,12 @@
1
+ export declare class BlueKiwiAuthError extends Error {
2
+ constructor(message?: string);
3
+ }
4
+ export declare class BlueKiwiApiError extends Error {
5
+ readonly status: number;
6
+ readonly body: string;
7
+ constructor(status: number, body: string);
8
+ }
9
+ export declare class BlueKiwiNetworkError extends Error {
10
+ readonly cause?: unknown | undefined;
11
+ constructor(message: string, cause?: unknown | undefined);
12
+ }
@@ -0,0 +1,24 @@
1
+ export class BlueKiwiAuthError extends Error {
2
+ constructor(message = "Invalid or expired API key") {
3
+ super(message);
4
+ this.name = "BlueKiwiAuthError";
5
+ }
6
+ }
7
+ export class BlueKiwiApiError extends Error {
8
+ status;
9
+ body;
10
+ constructor(status, body) {
11
+ super(`BlueKiwi API error ${status}: ${body}`);
12
+ this.status = status;
13
+ this.body = body;
14
+ this.name = "BlueKiwiApiError";
15
+ }
16
+ }
17
+ export class BlueKiwiNetworkError extends Error {
18
+ cause;
19
+ constructor(message, cause) {
20
+ super(message);
21
+ this.cause = cause;
22
+ this.name = "BlueKiwiNetworkError";
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bluekiwi",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "BlueKiwi CLI — install MCP client and skills into your agent runtime",
5
5
  "license": "MIT",
6
6
  "repository": {