@kweaver-ai/kweaver-sdk 0.6.2 → 0.6.4

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
@@ -31,6 +31,8 @@ export KWEAVER_BASE_URL=https://your-kweaver-instance.com
31
31
  export KWEAVER_TOKEN=your-token
32
32
  ```
33
33
 
34
+ With both set, API commands use that token even if you never ran `auth login`. You can also run **`kweaver auth status`**, **`kweaver auth whoami`** (supports `--json`), and **`kweaver config show`** when there is **no** current platform in `~/.kweaver/` — the CLI decodes the token locally (JWT only). If the token is opaque, identity fields are omitted and a short hint is printed.
35
+
34
36
  ### Business domain (platform)
35
37
 
36
38
  Set or verify **before** calling list/query APIs that scope by tenant. DIP deployments often need a UUID, not only `bd_public`.
@@ -151,11 +153,13 @@ const skillMd = await client.skills.fetchContent("skill-id");
151
153
  ## CLI Reference
152
154
 
153
155
  ```
154
- kweaver auth login <url> [--alias name] [--no-auth] [--no-browser] [-u user] [-p pass] [--playwright] [--insecure|-k]
156
+ kweaver auth login <url> [--alias name] [--no-auth] [--no-browser] [-u user] [-p pass] [--http-signin] [--playwright] [--insecure|-k]
157
+ # -u/-p: tries HTTP /oauth2/signin first (refresh_token). If studioweb is missing: falls back to Playwright when installed, else prints install hint. --http-signin: HTTP only. --playwright: force browser automation.
155
158
  kweaver auth login <url> --client-id ID --client-secret S --refresh-token T (headless login)
156
159
  kweaver auth export [url|alias] [--json] (export command to run on a headless host)
157
- kweaver auth status/list/use/delete/logout
158
- kweaver config show / list-bd / set-bd <value> # platform business domain — after login
160
+ kweaver auth status / whoami [url|alias] [--json] # whoami: --json; with KWEAVER_BASE_URL+KWEAVER_TOKEN when no ~/.kweaver/ platform
161
+ kweaver auth list/use/delete/logout
162
+ kweaver config show / list-bd / set-bd <value> # platform business domain — show/list-bd work with KWEAVER_BASE_URL (+ KWEAVER_TOKEN for list-bd)
159
163
  kweaver token
160
164
  kweaver ds list/get/delete/tables/connect
161
165
  kweaver ds import-csv <ds_id> --files <glob> [--table-prefix <p>] [--batch-size 500] [--recreate]
package/README.zh.md CHANGED
@@ -31,6 +31,8 @@ export KWEAVER_BASE_URL=https://your-kweaver-instance.com
31
31
  export KWEAVER_TOKEN=your-token
32
32
  ```
33
33
 
34
+ 两者同时设置时,即使未执行 `auth login`,业务命令也会使用该 token。若 **`~/.kweaver/` 无当前平台**,仍可使用 **`kweaver auth status`**、**`kweaver auth whoami`**(支持 `--json`)、**`kweaver config show`**:CLI 会在本地解 JWT 展示身份;若 token 为 opaque,则省略身份字段并给出简短提示。
35
+
34
36
  ### 业务域(平台配置)
35
37
 
36
38
  在调用依赖租户范围的接口前,应先确认业务域;DIP 环境通常使用 **UUID**,不能长期只依赖默认 `bd_public`。
@@ -144,11 +146,13 @@ const skillMd = await client.skills.fetchContent("skill-id");
144
146
  ## 命令速查
145
147
 
146
148
  ```
147
- kweaver auth login <url> [--alias name] [--no-auth] [--no-browser] [-u user] [-p pass] [--playwright] [--insecure|-k]
149
+ kweaver auth login <url> [--alias name] [--no-auth] [--no-browser] [-u user] [-p pass] [--http-signin] [--playwright] [--insecure|-k]
150
+ # -u/-p:默认先试 HTTP /oauth2/signin(可拿 refresh_token);无 studioweb 时:已装 Playwright 则回退无头浏览器,否则提示安装 Playwright;--http-signin 仅 HTTP;--playwright 强制浏览器
148
151
  kweaver auth login <url> --client-id ID --client-secret S --refresh-token T (无浏览器登录)
149
152
  kweaver auth export [url|alias] [--json] (导出在无浏览器机器上运行的命令)
150
- kweaver auth status/list/use/delete/logout
151
- kweaver config show / list-bd / set-bd <value> # 平台业务域,登录后优先
153
+ kweaver auth status / whoami [url|alias] [--json] # whoami 支持 --json;无 ~/.kweaver/ 当前平台时可配 KWEAVER_BASE_URL+KWEAVER_TOKEN
154
+ kweaver auth list/use/delete/logout
155
+ kweaver config show / list-bd / set-bd <value> # 业务域;show/list-bd 在无已保存平台时可与 env 配对
152
156
  kweaver token
153
157
  kweaver ds list/get/delete/tables/connect
154
158
  kweaver dataflow list/run/runs/logs
@@ -82,7 +82,10 @@ export async function pollDataflowResults(options) {
82
82
  return latest;
83
83
  }
84
84
  if (latest.status === "failed" || latest.status === "error") {
85
- const reason = latest.reason ? `: ${latest.reason}` : "";
85
+ const reasonVal = latest.reason;
86
+ const reason = reasonVal
87
+ ? `: ${typeof reasonVal === "string" ? reasonVal : JSON.stringify(reasonVal)}`
88
+ : "";
86
89
  throw new Error(`Dataflow run ${latest.status}${reason}`);
87
90
  }
88
91
  }
@@ -1,7 +1,7 @@
1
1
  export type SkillStatus = "unpublish" | "published" | "offline";
2
2
  export type SkillFileType = "zip" | "content";
3
3
  export interface SkillSummary {
4
- skill_id: string;
4
+ id: string;
5
5
  name: string;
6
6
  description?: string;
7
7
  version?: string;
@@ -26,20 +26,20 @@ export interface SkillFileSummary {
26
26
  mime_type?: string;
27
27
  }
28
28
  export interface SkillContentIndex {
29
- skill_id: string;
29
+ id: string;
30
30
  url: string;
31
31
  files: SkillFileSummary[];
32
32
  status?: SkillStatus;
33
33
  }
34
34
  export interface SkillFileReadResult {
35
- skill_id: string;
35
+ id: string;
36
36
  rel_path: string;
37
37
  url: string;
38
38
  mime_type?: string;
39
39
  file_type?: string;
40
40
  }
41
41
  export interface RegisterSkillResult {
42
- skill_id: string;
42
+ id: string;
43
43
  name: string;
44
44
  description?: string;
45
45
  version?: string;
@@ -47,11 +47,11 @@ export interface RegisterSkillResult {
47
47
  files?: string[];
48
48
  }
49
49
  export interface DeleteSkillResult {
50
- skill_id: string;
50
+ id: string;
51
51
  deleted: boolean;
52
52
  }
53
53
  export interface UpdateSkillStatusResult {
54
- skill_id: string;
54
+ id: string;
55
55
  status: SkillStatus;
56
56
  }
57
57
  export interface SkillListResult {
@@ -18,6 +18,20 @@ function unwrapEnvelope(raw) {
18
18
  }
19
19
  return parsed;
20
20
  }
21
+ /** Rename `skill_id` → `id` for consistent output with other modules. */
22
+ function normalizeSkillId(obj) {
23
+ if (!obj || typeof obj !== "object")
24
+ return obj;
25
+ if (Array.isArray(obj))
26
+ return obj.map(normalizeSkillId);
27
+ const record = obj;
28
+ const out = {};
29
+ for (const [key, value] of Object.entries(record)) {
30
+ const newKey = key === "skill_id" ? "id" : key;
31
+ out[newKey] = typeof value === "object" ? normalizeSkillId(value) : value;
32
+ }
33
+ return out;
34
+ }
21
35
  function appendCommonListParams(url, opts) {
22
36
  if (opts.page !== undefined)
23
37
  url.searchParams.set("page", String(opts.page));
@@ -60,23 +74,23 @@ export async function listSkills(options) {
60
74
  if (options.createUser)
61
75
  url.searchParams.set("create_user", options.createUser);
62
76
  const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
63
- return unwrapEnvelope(body);
77
+ return normalizeSkillId(unwrapEnvelope(body));
64
78
  }
65
79
  export async function listSkillMarket(options) {
66
80
  const url = new URL(buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/market`));
67
81
  appendCommonListParams(url, options);
68
82
  const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
69
- return unwrapEnvelope(body);
83
+ return normalizeSkillId(unwrapEnvelope(body));
70
84
  }
71
85
  export async function getSkill(options) {
72
86
  const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}`);
73
87
  const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
74
- return unwrapEnvelope(body);
88
+ return normalizeSkillId(unwrapEnvelope(body));
75
89
  }
76
90
  export async function deleteSkill(options) {
77
91
  const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}`);
78
92
  const { body } = await fetchTextOrThrow(url, { method: "DELETE", headers: baseHeaders(options) });
79
- return unwrapEnvelope(body);
93
+ return normalizeSkillId(unwrapEnvelope(body));
80
94
  }
81
95
  export async function updateSkillStatus(options) {
82
96
  const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/status`);
@@ -85,7 +99,7 @@ export async function updateSkillStatus(options) {
85
99
  headers: { ...baseHeaders(options), "content-type": "application/json" },
86
100
  body: JSON.stringify({ status: options.status }),
87
101
  });
88
- return unwrapEnvelope(body);
102
+ return normalizeSkillId(unwrapEnvelope(body));
89
103
  }
90
104
  export async function registerSkillContent(options) {
91
105
  const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills`);
@@ -102,7 +116,7 @@ export async function registerSkillContent(options) {
102
116
  headers: { ...baseHeaders(options), "content-type": "application/json" },
103
117
  body: JSON.stringify(payload),
104
118
  });
105
- return unwrapEnvelope(body);
119
+ return normalizeSkillId(unwrapEnvelope(body));
106
120
  }
107
121
  export async function registerSkillZip(options) {
108
122
  const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills`);
@@ -118,12 +132,12 @@ export async function registerSkillZip(options) {
118
132
  headers: baseHeaders(options),
119
133
  body: form,
120
134
  });
121
- return unwrapEnvelope(body);
135
+ return normalizeSkillId(unwrapEnvelope(body));
122
136
  }
123
137
  export async function getSkillContentIndex(options) {
124
138
  const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/content`);
125
139
  const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
126
- return unwrapEnvelope(body);
140
+ return normalizeSkillId(unwrapEnvelope(body));
127
141
  }
128
142
  export async function fetchSkillContent(options) {
129
143
  const index = await getSkillContentIndex(options);
@@ -137,7 +151,7 @@ export async function readSkillFile(options) {
137
151
  headers: { ...baseHeaders(options), "content-type": "application/json" },
138
152
  body: JSON.stringify({ rel_path: options.relPath }),
139
153
  });
140
- return unwrapEnvelope(body);
154
+ return normalizeSkillId(unwrapEnvelope(body));
141
155
  }
142
156
  export async function fetchSkillFile(options) {
143
157
  const file = await readSkillFile(options);
@@ -235,4 +235,6 @@ export interface ListAllVegaResourcesOptions {
235
235
  offset?: number;
236
236
  businessDomain?: string;
237
237
  }
238
+ /** List all Vega resources (no catalog filter). Uses GET /resources — not /resources/list, which
239
+ * conflicts with GET /resources/{id} on some gateways (path segment "list" is treated as an id). */
238
240
  export declare function listAllVegaResources(options: ListAllVegaResourcesOptions): Promise<string>;
package/dist/api/vega.js CHANGED
@@ -476,20 +476,15 @@ export async function vegaSQLQuery(options) {
476
476
  throw new HttpError(response.status, response.statusText, body);
477
477
  return body;
478
478
  }
479
+ /** List all Vega resources (no catalog filter). Uses GET /resources — not /resources/list, which
480
+ * conflicts with GET /resources/{id} on some gateways (path segment "list" is treated as an id). */
479
481
  export async function listAllVegaResources(options) {
480
482
  const { baseUrl, accessToken, limit, offset, businessDomain = "bd_public" } = options;
481
- const base = baseUrl.replace(/\/+$/, "");
482
- const url = new URL(`${base}${VEGA_BASE}/resources/list`);
483
- if (limit !== undefined)
484
- url.searchParams.set("limit", String(limit));
485
- if (offset !== undefined)
486
- url.searchParams.set("offset", String(offset));
487
- const response = await fetch(url.toString(), {
488
- method: "GET",
489
- headers: buildHeaders(accessToken, businessDomain),
483
+ return listVegaResources({
484
+ baseUrl,
485
+ accessToken,
486
+ limit,
487
+ offset,
488
+ businessDomain,
490
489
  });
491
- const body = await response.text();
492
- if (!response.ok)
493
- throw new HttpError(response.status, response.statusText, body);
494
- return body;
495
490
  }
@@ -1,4 +1,19 @@
1
1
  import { type TokenConfig } from "../config/store.js";
2
+ /**
3
+ * Studioweb hardcoded LOGIN public key (PEM) — the single key used for HTTP `/oauth2/signin`.
4
+ * Source: kweaver-ai/kweaver `deploy/auto_cofig/auto_config.sh` `LOGIN_PUBLIC_KEY`.
5
+ */
6
+ export declare const STUDIOWEB_LOGIN_PUBLIC_KEY_PEM = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyOstgbYuubBi2PUqeVj\nGKlkwVUY6w1Y8d4k116dI2SkZI8fxcjHALv77kItO4jYLVplk9gO4HAtsisnNE2o\nwlYIqdmyEPMwupaeFFFcg751oiTXJiYbtX7ABzU5KQYPjRSEjMq6i5qu/mL67XTk\nhvKwrC83zme66qaKApmKupDODPb0RRkutK/zHfd1zL7sciBQ6psnNadh8pE24w8O\n2XVy1v2bgSNkGHABgncR7seyIg81JQ3c/Axxd6GsTztjLnlvGAlmT1TphE84mi99\nfUaGD2A1u1qdIuNc+XuisFeNcUW6fct0+x97eS2eEGRr/7qxWmO/P20sFVzXc2bF\n1QIDAQAB\n-----END PUBLIC KEY-----";
7
+ /**
8
+ * Default RSA modulus (hex) for `/oauth2/signin` when `__NEXT_DATA__` has no `publicKey` / `modulus`.
9
+ * DIP / EACP / AnyShare-style deployments use the ISFWeb `core/auth` PUBLIC_KEY (1024-bit, exp 65537).
10
+ * Prefer key material from the sign-in page when present.
11
+ */
12
+ export declare const DEFAULT_SIGNIN_RSA_MODULUS_HEX = "C1D9F84B95AF6B331FBA2D64D76A39CAD7529DA79DB4B3543E4DF3DF21723FEC6F7E2F6602E11037339AE0462DF6B39F94150FC256A505A8CA95BB3699E25C3FB84764D6A1DC3F483A2C1DC4F70925D85725151D0CFBF1EB5A6C4FA0E37ED32FED150C717CD82C528745CDB761D17635AC855421B3CBBEE7D405B2CA5C70CFA7";
13
+ /**
14
+ * Build an SPKI PEM from an RSA modulus (hex) and public exponent (default 65537 / 0x10001).
15
+ */
16
+ export declare function rsaModulusHexToSpkiPem(modulusHex: string, exponent?: number): string;
2
17
  /** POSIX shell single-quote escaping for copy-paste commands. */
3
18
  export declare function shellQuoteForShell(value: string): string;
4
19
  /**
@@ -11,6 +26,12 @@ export declare function buildCopyCommand(baseUrl: string, clientId: string, clie
11
26
  */
12
27
  export declare function buildCallbackHtml(copyCommand: string): string;
13
28
  export declare function normalizeBaseUrl(value: string): string;
29
+ /**
30
+ * Temporarily disable TLS certificate verification for Node `fetch` (sets
31
+ * NODE_TLS_REJECT_UNAUTHORIZED). Used for `--insecure` login and token refresh.
32
+ */
33
+ /** @internal Exported for CLI env-only identity resolution (`env-snapshot.ts`). */
34
+ export declare function runWithTlsInsecure<T>(tlsInsecure: boolean | undefined, fn: () => Promise<T>): Promise<T>;
14
35
  /**
15
36
  * OAuth2 Authorization Code login flow.
16
37
  * 1. Register client (if not already registered), OR use a provided client ID
@@ -50,6 +71,54 @@ export declare function playwrightLogin(baseUrl: string, options?: {
50
71
  scope?: string;
51
72
  tlsInsecure?: boolean;
52
73
  }): Promise<TokenConfig>;
74
+ /**
75
+ * Parse Next.js `__NEXT_DATA__` from the OAuth2 sign-in HTML shell (CSRF + optional challenge/remember for POST /oauth2/signin).
76
+ * Hydra `login_challenge` may appear only in the sign-in URL; use that when `pageProps.challenge` is absent.
77
+ */
78
+ export declare function parseSigninPageHtmlProps(html: string): {
79
+ challenge?: string;
80
+ csrftoken: string;
81
+ remember?: boolean;
82
+ /** Hex modulus, PEM, or Base64 SPKI from page (nested search + HTML regex fallback). */
83
+ rsaPublicKeyMaterial?: string;
84
+ };
85
+ /**
86
+ * True when {@link oauth2PasswordSigninLogin} failed because the Studio web sign-in shell
87
+ * (`/interface/studioweb/login`) is missing or unreachable — callers may fall back to Playwright.
88
+ */
89
+ export declare function isStudiowebShellUnavailableError(err: unknown): boolean;
90
+ /**
91
+ * OAuth2 Authorization Code login using HTTP **only**: `GET /oauth2/signin` (Next.js shell) and
92
+ * `POST /oauth2/signin` with an RSA PKCS#1 v1.5–encrypted password (same as the browser `rsa.min` / Studio
93
+ * `core/mediator/auth` path).
94
+ *
95
+ * `/oauth2/auth` uses `product` `adp` by default (KWeaver Studio shell); set `oauthProduct` or `KWEAVER_OAUTH_PRODUCT` for DIP (`dip`).
96
+ * Password ciphertext defaults to **single-line base64** (PyCrypto-style); set `KWEAVER_SIGNIN_PASSWORD_B64_RSA_MIN=1` for rsa.min-style wrapped lines.
97
+ */
98
+ export declare function oauth2PasswordSigninLogin(baseUrl: string, options: {
99
+ username: string;
100
+ password: string;
101
+ port?: number;
102
+ scope?: string;
103
+ clientId?: string;
104
+ clientSecret?: string;
105
+ tlsInsecure?: boolean;
106
+ /**
107
+ * `product` query for `/oauth2/auth` (must match deployment). Default `adp`; DIP deployments often use `dip`.
108
+ * @default KWEAVER_OAUTH_PRODUCT env or `adp`
109
+ */
110
+ oauthProduct?: string;
111
+ /**
112
+ * Password ciphertext: `rsa.min` uses newline every 64 chars; PyCrypto / some gateways expect a single base64 line.
113
+ * @default false (single-line base64, matches kweaver-core EACP-style encryption)
114
+ */
115
+ signinPasswordBase64Plain?: boolean;
116
+ /**
117
+ * PEM / hex / Base64-SPKI file path — overrides key from the sign-in HTML.
118
+ * Env: `KWEAVER_SIGNIN_RSA_PUBLIC_KEY` (same path semantics as CLI `--signin-public-key-file`).
119
+ */
120
+ signinPublicKeyPemPath?: string;
121
+ }): Promise<TokenConfig>;
53
122
  /**
54
123
  * Log in on a headless machine using OAuth2 client credentials and a refresh token (no browser).
55
124
  * Exchanges the refresh token for a new access token and persists ~/.kweaver/ state.