@kalera/munin-sdk 1.2.5 → 1.2.8

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @kalera/munin-sdk@1.2.5 build /home/runner/work/munin-for-agents/munin-for-agents/packages/ts-sdk
2
+ > @kalera/munin-sdk@1.2.8 build /home/runner/work/munin-for-agents/munin-for-agents/packages/ts-sdk
3
3
  > tsc -p tsconfig.json
4
4
 
package/dist/client.d.ts CHANGED
@@ -1,12 +1,11 @@
1
- import type { MuninAction, MuninCapabilities, MuninClientConfig, MuninResponse } from "./types.js";
1
+ import type { MuninAction, MuninClientConfig, MuninResponse } from "./types.js";
2
2
  export declare class MuninClient {
3
3
  private readonly baseUrl;
4
4
  private readonly apiKey?;
5
5
  private readonly timeoutMs;
6
6
  private readonly fetchImpl;
7
- private capabilitiesCache?;
8
7
  constructor(config?: MuninClientConfig);
9
- capabilities(forceRefresh?: boolean): Promise<MuninCapabilities>;
8
+ capabilities(forceRefresh?: boolean): Promise<import("./types.js").MuninCapabilities>;
10
9
  invoke<TPayload extends Record<string, unknown>, TData = unknown>(projectId: string, action: MuninAction, payload: TPayload, options?: {
11
10
  requestId?: string;
12
11
  ensureCapability?: boolean;
package/dist/client.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { MuninSdkError, MuninTransportError } from "./errors.js";
2
- import { fetchCapabilities, isActionSupported, } from "./capabilities.js";
2
+ import { fetchCapabilities, isActionSupported } from "./capabilities.js";
3
3
  const DEFAULT_TIMEOUT_MS = 15_000;
4
4
  export class MuninClient {
5
5
  baseUrl;
6
6
  apiKey;
7
7
  timeoutMs;
8
8
  fetchImpl;
9
- capabilitiesCache;
10
9
  constructor(config) {
11
10
  this.baseUrl = (config?.baseUrl || "https://munin.kalera.dev").replace(/\/$/, "");
12
11
  this.apiKey = config?.apiKey;
@@ -14,11 +13,11 @@ export class MuninClient {
14
13
  this.fetchImpl = config?.fetchImpl ?? fetch;
15
14
  }
16
15
  async capabilities(forceRefresh = false) {
17
- if (this.capabilitiesCache && !forceRefresh) {
18
- return this.capabilitiesCache;
16
+ if (!forceRefresh && globalThis.__munin_caps) {
17
+ return globalThis.__munin_caps;
19
18
  }
20
19
  const caps = await fetchCapabilities(this.baseUrl, this.apiKey, this.fetchImpl);
21
- this.capabilitiesCache = caps;
20
+ globalThis.__munin_caps = caps;
22
21
  return caps;
23
22
  }
24
23
  async invoke(projectId, action, payload, options) {
@@ -31,41 +30,53 @@ export class MuninClient {
31
30
  });
32
31
  }
33
32
  }
34
- const request = {
35
- apiKey: this.apiKey,
36
- project: projectId,
37
- projectId: projectId, // Fallback for un-restarted server
38
- action,
39
- payload,
40
- requestId: options?.requestId,
41
- client: {
42
- name: "@kalera/munin-sdk",
43
- version: "1.0.0",
44
- },
45
- };
46
33
  const controller = new AbortController();
47
34
  const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
48
- const response = await this.fetchImpl(`${this.baseUrl}/api/mcp/action`, {
49
- method: "POST",
50
- headers: {
51
- "Content-Type": "application/json",
52
- },
53
- body: JSON.stringify(request),
54
- signal: controller.signal,
55
- }).catch((error) => {
35
+ let response;
36
+ try {
37
+ response = await this.fetchImpl(`${this.baseUrl}/api/mcp/action`, {
38
+ method: "POST",
39
+ headers: {
40
+ "Content-Type": "application/json",
41
+ ...(this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}),
42
+ },
43
+ body: JSON.stringify({
44
+ action,
45
+ project: projectId,
46
+ projectId, // Fallback for un-restarted server
47
+ payload,
48
+ requestId: options?.requestId,
49
+ client: {
50
+ name: "@kalera/munin-sdk",
51
+ version: "1.0.0",
52
+ },
53
+ }),
54
+ signal: controller.signal,
55
+ });
56
+ }
57
+ catch (error) {
58
+ clearTimeout(timeout);
56
59
  throw new MuninTransportError(`Request failed for action '${action}': ${String(error)}`);
57
- });
60
+ }
58
61
  clearTimeout(timeout);
59
- const body = (await response.json());
60
- if (!response.ok || (body.ok === false) || (body.success === false)) {
62
+ let body;
63
+ try {
64
+ body = await response.json();
65
+ }
66
+ catch {
67
+ throw new MuninTransportError(`Invalid JSON response for action '${action}'`);
68
+ }
69
+ if (!response.ok || !isResponseOk(body)) {
61
70
  let errObj = body.error;
62
- if (typeof errObj === 'string') {
71
+ if (typeof errObj === "string") {
63
72
  errObj = { code: "INTERNAL_ERROR", message: errObj };
64
73
  }
65
- throw new MuninSdkError(errObj ?? {
66
- code: "INTERNAL_ERROR",
67
- message: `Unexpected failure invoking action '${action}'`,
68
- });
74
+ throw new MuninSdkError((typeof errObj === "object" && errObj !== null && "code" in errObj && "message" in errObj)
75
+ ? errObj
76
+ : {
77
+ code: "INTERNAL_ERROR",
78
+ message: `Unexpected failure invoking action '${action}'`,
79
+ });
69
80
  }
70
81
  return body;
71
82
  }
@@ -88,3 +99,10 @@ export class MuninClient {
88
99
  return this.invoke(projectId, "share", { memoryIds, targetProjectIds }, { ensureCapability: true });
89
100
  }
90
101
  }
102
+ /** Narrow a raw JSON value to a response-like object. */
103
+ function isResponseOk(body) {
104
+ if (typeof body !== "object" || body === null)
105
+ return false;
106
+ const obj = body;
107
+ return obj.ok === true;
108
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kalera/munin-sdk",
3
- "version": "1.2.5",
3
+ "version": "1.2.8",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/client.ts CHANGED
@@ -1,12 +1,7 @@
1
1
  import { MuninSdkError, MuninTransportError } from "./errors.js";
2
- import {
3
- fetchCapabilities,
4
- isActionSupported,
5
- } from "./capabilities.js";
2
+ import { fetchCapabilities, isActionSupported } from "./capabilities.js";
6
3
  import type {
7
4
  MuninAction,
8
- MuninActionEnvelope,
9
- MuninCapabilities,
10
5
  MuninClientConfig,
11
6
  MuninResponse,
12
7
  } from "./types.js";
@@ -18,7 +13,6 @@ export class MuninClient {
18
13
  private readonly apiKey?: string;
19
14
  private readonly timeoutMs: number;
20
15
  private readonly fetchImpl: typeof fetch;
21
- private capabilitiesCache?: MuninCapabilities;
22
16
 
23
17
  constructor(config?: MuninClientConfig) {
24
18
  this.baseUrl = (config?.baseUrl || "https://munin.kalera.dev").replace(/\/$/, "");
@@ -27,17 +21,12 @@ export class MuninClient {
27
21
  this.fetchImpl = config?.fetchImpl ?? fetch;
28
22
  }
29
23
 
30
- async capabilities(forceRefresh = false): Promise<MuninCapabilities> {
31
- if (this.capabilitiesCache && !forceRefresh) {
32
- return this.capabilitiesCache;
24
+ async capabilities(forceRefresh = false) {
25
+ if (!forceRefresh && (globalThis as Record<string, unknown>).__munin_caps) {
26
+ return (globalThis as Record<string, unknown>).__munin_caps as Awaited<ReturnType<typeof fetchCapabilities>>;
33
27
  }
34
-
35
- const caps = await fetchCapabilities(
36
- this.baseUrl,
37
- this.apiKey,
38
- this.fetchImpl,
39
- );
40
- this.capabilitiesCache = caps;
28
+ const caps = await fetchCapabilities(this.baseUrl, this.apiKey, this.fetchImpl);
29
+ (globalThis as Record<string, unknown>).__munin_caps = caps;
41
30
  return caps;
42
31
  }
43
32
 
@@ -57,77 +46,99 @@ export class MuninClient {
57
46
  }
58
47
  }
59
48
 
60
- const request = {
61
- apiKey: this.apiKey,
62
- project: projectId,
63
- projectId: projectId, // Fallback for un-restarted server
64
- action,
65
- payload,
66
- requestId: options?.requestId,
67
- client: {
68
- name: "@kalera/munin-sdk",
69
- version: "1.0.0",
70
- },
71
- };
72
-
73
49
  const controller = new AbortController();
74
50
  const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
75
51
 
76
- const response = await this.fetchImpl(`${this.baseUrl}/api/mcp/action`, {
77
- method: "POST",
78
- headers: {
79
- "Content-Type": "application/json",
80
- },
81
- body: JSON.stringify(request),
82
- signal: controller.signal,
83
- }).catch((error: unknown) => {
52
+ let response: Response;
53
+ try {
54
+ response = await this.fetchImpl(`${this.baseUrl}/api/mcp/action`, {
55
+ method: "POST",
56
+ headers: {
57
+ "Content-Type": "application/json",
58
+ ...(this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}),
59
+ },
60
+ body: JSON.stringify({
61
+ action,
62
+ project: projectId,
63
+ projectId, // Fallback for un-restarted server
64
+ payload,
65
+ requestId: options?.requestId,
66
+ client: {
67
+ name: "@kalera/munin-sdk",
68
+ version: "1.0.0",
69
+ },
70
+ }),
71
+ signal: controller.signal,
72
+ });
73
+ } catch (error) {
74
+ clearTimeout(timeout);
84
75
  throw new MuninTransportError(
85
76
  `Request failed for action '${action}': ${String(error)}`,
86
77
  );
87
- });
78
+ }
88
79
 
89
80
  clearTimeout(timeout);
90
81
 
91
- const body = (await response.json()) as any;
82
+ let body: unknown;
83
+ try {
84
+ body = await response.json();
85
+ } catch {
86
+ throw new MuninTransportError(
87
+ `Invalid JSON response for action '${action}'`,
88
+ );
89
+ }
92
90
 
93
- if (!response.ok || (body.ok === false) || (body.success === false)) {
94
- let errObj = body.error;
95
- if (typeof errObj === 'string') {
91
+ if (!response.ok || !isResponseOk(body)) {
92
+ let errObj = (body as Record<string, unknown>).error;
93
+ if (typeof errObj === "string") {
96
94
  errObj = { code: "INTERNAL_ERROR", message: errObj };
97
95
  }
98
-
96
+
99
97
  throw new MuninSdkError(
100
- errObj ?? {
101
- code: "INTERNAL_ERROR",
102
- message: `Unexpected failure invoking action '${action}'`,
103
- },
98
+ (typeof errObj === "object" && errObj !== null && "code" in errObj && "message" in errObj)
99
+ ? (errObj as { code: "AUTH_INVALID" | "FEATURE_DISABLED" | "NOT_FOUND" | "RATE_LIMITED" | "VALIDATION_ERROR" | "INTERNAL_ERROR"; message: string })
100
+ : {
101
+ code: "INTERNAL_ERROR" as const,
102
+ message: `Unexpected failure invoking action '${action}'`,
103
+ },
104
104
  );
105
105
  }
106
106
 
107
- return body;
107
+ return body as MuninResponse<TData>;
108
108
  }
109
109
 
110
- async store(projectId: string, payload: Record<string, unknown>) {
110
+ async store(projectId: string, payload: Record<string, unknown>): Promise<MuninResponse<unknown>> {
111
111
  return this.invoke(projectId, "store", payload, { ensureCapability: true });
112
112
  }
113
113
 
114
- async retrieve(projectId: string, payload: Record<string, unknown>) {
114
+ async retrieve(projectId: string, payload: Record<string, unknown>): Promise<MuninResponse<unknown>> {
115
115
  return this.invoke(projectId, "retrieve", payload, { ensureCapability: true });
116
116
  }
117
117
 
118
- async search(projectId: string, payload: Record<string, unknown>) {
118
+ async search(projectId: string, payload: Record<string, unknown>): Promise<MuninResponse<unknown>> {
119
119
  return this.invoke(projectId, "search", payload, { ensureCapability: true });
120
120
  }
121
121
 
122
- async list(projectId: string, payload: Record<string, unknown> = {}) {
122
+ async list(projectId: string, payload: Record<string, unknown> = {}): Promise<MuninResponse<unknown>> {
123
123
  return this.invoke(projectId, "list", payload, { ensureCapability: true });
124
124
  }
125
125
 
126
- async recent(projectId: string, payload: Record<string, unknown> = {}) {
126
+ async recent(projectId: string, payload: Record<string, unknown> = {}): Promise<MuninResponse<unknown>> {
127
127
  return this.invoke(projectId, "recent", payload, { ensureCapability: true });
128
128
  }
129
129
 
130
- async share(projectId: string, memoryIds: string[], targetProjectIds: string[]) {
130
+ async share(
131
+ projectId: string,
132
+ memoryIds: string[],
133
+ targetProjectIds: string[],
134
+ ): Promise<MuninResponse<unknown>> {
131
135
  return this.invoke(projectId, "share", { memoryIds, targetProjectIds }, { ensureCapability: true });
132
136
  }
133
137
  }
138
+
139
+ /** Narrow a raw JSON value to a response-like object. */
140
+ function isResponseOk(body: unknown): boolean {
141
+ if (typeof body !== "object" || body === null) return false;
142
+ const obj = body as Record<string, unknown>;
143
+ return obj.ok === true;
144
+ }