@kweaver-ai/kweaver-sdk 0.4.2 → 0.4.5

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.
@@ -254,7 +254,8 @@ export async function sendChatRequest(options) {
254
254
  };
255
255
  if (verbose) {
256
256
  console.error(`POST ${url}`);
257
- console.error(`Headers: ${JSON.stringify(headers)}`);
257
+ const safeHeaders = Object.fromEntries(Object.entries(headers).map(([k, v]) => k.toLowerCase() === "authorization" ? [k, "Bearer ***"] : [k, v]));
258
+ console.error(`Headers: ${JSON.stringify(safeHeaders)}`);
258
259
  console.error(`Body: ${JSON.stringify(body)}`);
259
260
  }
260
261
  let response;
@@ -312,7 +313,8 @@ export async function sendChatRequestStream(options, callbacks) {
312
313
  };
313
314
  if (verbose) {
314
315
  console.error(`POST ${url}`);
315
- console.error(`Headers: ${JSON.stringify(headers)}`);
316
+ const safeHeaders = Object.fromEntries(Object.entries(headers).map(([k, v]) => k.toLowerCase() === "authorization" ? [k, "Bearer ***"] : [k, v]));
317
+ console.error(`Headers: ${JSON.stringify(safeHeaders)}`);
316
318
  console.error(`Body: ${JSON.stringify(body)}`);
317
319
  }
318
320
  let response;
@@ -1,5 +1,6 @@
1
1
  import { fetchTextOrThrow } from "../utils/http.js";
2
2
  const MCP_PROTOCOL_VERSION = "2024-11-05";
3
+ const SESSION_TTL_MS = 300_000; // 5 minutes
3
4
  const sessionCache = new Map();
4
5
  function sessionKey(options) {
5
6
  return `${options.mcpUrl}:${options.knId}`;
@@ -20,8 +21,11 @@ function buildHeaders(options, sessionId) {
20
21
  async function ensureSession(options) {
21
22
  const key = sessionKey(options);
22
23
  const cached = sessionCache.get(key);
24
+ if (cached && Date.now() - cached.createdAt < SESSION_TTL_MS)
25
+ return cached.id;
26
+ // Remove stale entry if expired
23
27
  if (cached)
24
- return cached;
28
+ sessionCache.delete(key);
25
29
  const initBody = JSON.stringify({
26
30
  jsonrpc: "2.0",
27
31
  id: 1,
@@ -50,7 +54,7 @@ async function ensureSession(options) {
50
54
  headers: buildHeaders(options, sessionId),
51
55
  body: initNotifBody,
52
56
  });
53
- sessionCache.set(key, sessionId);
57
+ sessionCache.set(key, { id: sessionId, createdAt: Date.now() });
54
58
  return sessionId;
55
59
  }
56
60
  function isMissingInputParams(obj) {
@@ -30,7 +30,7 @@ export async function listConversations(opts) {
30
30
  }
31
31
  const body = await response.text();
32
32
  if (!response.ok) {
33
- return "[]";
33
+ throw new Error(`listConversations failed: HTTP ${response.status} ${response.statusText} — ${body.slice(0, 200)}`);
34
34
  }
35
35
  return body || "[]";
36
36
  }
@@ -58,7 +58,7 @@ export async function listMessages(opts) {
58
58
  }
59
59
  const body = await response.text();
60
60
  if (!response.ok) {
61
- return "[]";
61
+ throw new Error(`listMessages failed: HTTP ${response.status} ${response.statusText} — ${body.slice(0, 200)}`);
62
62
  }
63
63
  return body || "[]";
64
64
  }
@@ -204,7 +204,8 @@ export async function scanMetadata(options) {
204
204
  const scanResult = await scanResponse.json();
205
205
  const taskId = scanResult.id ?? "";
206
206
  for (let i = 0; i < 30; i += 1) {
207
- await new Promise((r) => setTimeout(r, 2000));
207
+ const delay = Math.min(2000 * Math.pow(1.5, i), 15000);
208
+ await new Promise((r) => setTimeout(r, delay));
208
209
  const statusResponse = await fetch(statusUrl(taskId), {
209
210
  method: "GET",
210
211
  headers: buildHeaders(accessToken, businessDomain),
package/dist/api/vega.js CHANGED
@@ -13,8 +13,11 @@ function buildHeaders(accessToken, businessDomain) {
13
13
  export async function vegaHealth(options) {
14
14
  const { baseUrl, accessToken, businessDomain = "bd_public", } = options;
15
15
  const base = baseUrl.replace(/\/+$/, "");
16
- const url = `${base}/health`;
17
- const response = await fetch(url, {
16
+ // Vega backend has no dedicated /health endpoint.
17
+ // Probe the catalogs list as a lightweight reachability check.
18
+ const url = new URL(`${base}${VEGA_BASE}/catalogs`);
19
+ url.searchParams.set("limit", "1");
20
+ const response = await fetch(url.toString(), {
18
21
  method: "GET",
19
22
  headers: buildHeaders(accessToken, businessDomain),
20
23
  });
@@ -22,7 +25,7 @@ export async function vegaHealth(options) {
22
25
  if (!response.ok) {
23
26
  throw new HttpError(response.status, response.statusText, body);
24
27
  }
25
- return body;
28
+ return JSON.stringify({ status: "healthy", probe: "catalogs", statusCode: response.status });
26
29
  }
27
30
  export async function listVegaCatalogs(options) {
28
31
  const { baseUrl, accessToken, status, limit, offset, businessDomain = "bd_public", } = options;
@@ -1,77 +1,24 @@
1
- import { type CallbackSession, type ClientConfig, type TokenConfig } from "../config/store.js";
2
- interface RegisterClientOptions {
3
- baseUrl: string;
4
- clientName: string;
5
- redirectUri: string;
6
- logoutRedirectUri: string;
7
- lang?: string;
8
- product?: string;
9
- xForwardedPrefix?: string;
10
- }
1
+ import { type TokenConfig } from "../config/store.js";
11
2
  export declare function normalizeBaseUrl(value: string): string;
12
- export declare function getAuthorizationSuccessMessage(): string;
13
- export declare function registerClient(options: RegisterClientOptions): Promise<ClientConfig>;
14
- export interface EnsureClientOptions {
15
- baseUrl: string;
16
- port: number;
17
- clientName: string;
18
- forceRegister: boolean;
19
- host?: string;
20
- redirectUriOverride?: string;
21
- lang?: string;
22
- product?: string;
23
- xForwardedPrefix?: string;
24
- }
25
- export interface EnsuredClientConfig {
26
- client: ClientConfig;
27
- created: boolean;
28
- }
29
- export interface AuthRedirectConfig {
30
- redirectUri: string;
31
- logoutRedirectUri: string;
32
- listenHost: string;
33
- listenPort: number;
34
- callbackPath: string;
35
- }
36
- export declare function buildAuthRedirectConfig(options: {
37
- port: number;
38
- host?: string;
39
- redirectUriOverride?: string;
40
- }): AuthRedirectConfig;
41
- export declare function ensureClientConfig(options: EnsureClientOptions): Promise<EnsuredClientConfig>;
42
- export declare function buildAuthorizationUrl(client: ClientConfig, state?: string): string;
3
+ export declare function playwrightLogin(baseUrl: string, options?: {
4
+ username?: string;
5
+ password?: string;
6
+ }): Promise<TokenConfig>;
43
7
  /**
44
- * Call the platform's end-session endpoint so the server invalidates the session.
45
- * Best-effort: failures are ignored so local logout still proceeds.
8
+ * Exchange refresh_token for a new access token (OAuth2 password grant style, same as Python ConfigAuth).
9
+ * Persists the new token to ~/.kweaver/ and returns it.
46
10
  */
47
- export declare function callLogoutEndpoint(client: ClientConfig, token: TokenConfig | null): Promise<void>;
48
- export declare function refreshAccessToken(client: ClientConfig, refreshToken: string): Promise<TokenConfig>;
11
+ export declare function refreshAccessToken(token: TokenConfig): Promise<TokenConfig>;
49
12
  export declare function ensureValidToken(opts?: {
50
13
  forceRefresh?: boolean;
51
14
  }): Promise<TokenConfig>;
52
- export interface AuthLoginOptions {
53
- baseUrl: string;
54
- port: number;
55
- clientName: string;
56
- open: boolean;
57
- forceRegister: boolean;
58
- host?: string;
59
- redirectUriOverride?: string;
60
- lang?: string;
61
- product?: string;
62
- xForwardedPrefix?: string;
63
- }
64
- export declare function login(options: AuthLoginOptions): Promise<{
65
- client: ClientConfig;
66
- token: TokenConfig;
67
- authorizationUrl: string;
68
- callback: CallbackSession;
69
- created: boolean;
70
- }>;
71
- export declare function getStoredAuthSummary(baseUrl?: string): {
72
- client: ClientConfig | null;
73
- token: TokenConfig | null;
74
- callback: CallbackSession | null;
75
- };
15
+ /**
16
+ * Run an operation; on HTTP 401, refresh the access token once and retry.
17
+ * Does not call `ensureValidToken` first — use for CLI routers so `--help` works without login.
18
+ */
19
+ export declare function with401RefreshRetry<T>(fn: () => Promise<T>): Promise<T>;
20
+ /**
21
+ * Load a valid token, run `fn(token)`, and on 401 refresh once and retry with the new token.
22
+ */
23
+ export declare function withTokenRetry<T>(fn: (token: TokenConfig) => Promise<T>): Promise<T>;
76
24
  export declare function formatHttpError(error: unknown): string;
77
- export {};