@kweaver-ai/kweaver-sdk 0.7.1 → 0.7.2

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,7 +31,7 @@ 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/`. In env-token mode, `whoami` resolves the bound identity from EACP `/api/eacp/v1/user/get` and prints `Type` (user/app), `User ID`, `Account` and `Name`; this works for both opaque and JWT tokens. If EACP is unreachable, the CLI falls back to local JWT decode and prints a short hint when the token is opaque.
34
+ With both set, API commands use that token even if you never ran `auth login`. The same applies to **`kweaver --base-url <url> --token <access-token> <command>`** (stateless flag mode; see [Stateless token mode](#stateless-token-mode)). You can also run **`kweaver auth status`**, **`kweaver auth whoami`** (supports `--json`), and **`kweaver config show`** when there is **no** current platform in `~/.kweaver/`. In env-token mode, `whoami` resolves the bound identity from EACP `/api/eacp/v1/user/get` and prints `Type` (user/app), `User ID`, `Account` and `Name`; this works for both opaque and JWT tokens. If EACP is unreachable, the CLI falls back to local JWT decode and prints a short hint when the token is opaque.
35
35
 
36
36
  `kweaver config list-bd` lists business domains for the current user. App (service) tokens are not bound to an end-user — when the backend rejects the call with `401 invalid user_id`, the CLI re-checks the token type via EACP and, if confirmed `type:"app"`, replaces the cryptic backend body with `This command does not support app accounts.`. Use a user token (interactive `auth login`) for user-bound endpoints.
37
37
 
@@ -188,8 +188,10 @@ kweaver bkn action-log list/get/cancel
188
188
  kweaver agent list/get/create/update/delete/chat/sessions/history/publish/unpublish
189
189
  kweaver skill list/market/get/register/status/delete/content/read-file/download/install
190
190
  kweaver vega health/stats/inspect/sql/catalog/resource/connector-type
191
- kweaver context-loader config set/use/list/show
192
- kweaver context-loader search-schema/tool-call/kn-search/query-object-instance/find-skills/...
191
+ kweaver context-loader tools|resources|templates|prompts <kn-id>
192
+ kweaver context-loader search-schema|tool-call|kn-search|kn-schema-search <kn-id> <query|name> [...]
193
+ kweaver context-loader query-object-instance|query-instance-subgraph|get-logic-properties|get-action-info|find-skills <kn-id> ...
194
+ kweaver context-loader config set/use/list/show (deprecated; <kn-id> may be omitted to fall back to saved config)
193
195
  kweaver toolbox create/list/publish/unpublish/delete
194
196
  kweaver tool upload/list/enable/disable
195
197
  kweaver call <path> [-X METHOD] [-d BODY] [-H header] [-F key=value]
@@ -251,10 +253,33 @@ kweaver tool enable --toolbox <BOX_ID> <TOOL_ID>
251
253
  | `KWEAVER_BASE_URL` | KWeaver instance URL |
252
254
  | `KWEAVER_BUSINESS_DOMAIN` | Business domain identifier |
253
255
  | `KWEAVER_TOKEN` | Access token |
256
+ | `KWEAVER_TOKEN_SOURCE` | Internal sentinel set by the CLI when `--token` is passed; do not set manually |
254
257
  | `KWEAVER_NO_AUTH` | Set to `1`/`true`/`yes` to use no-auth sentinel when `KWEAVER_TOKEN` is unset (with `KWEAVER_BASE_URL` or active platform) |
255
258
  | `KWEAVER_TLS_INSECURE` | Set to `1` or `true` to skip TLS certificate verification for all HTTPS in the process (dev only; prefer `kweaver auth … --insecure` which saves per platform) |
256
259
  | `NODE_TLS_REJECT_UNAUTHORIZED` | Node.js built-in TLS switch: set to `0` to skip certificate verification for HTTPS in this process. The `kweaver` CLI sets this when `KWEAVER_TLS_INSECURE` is set or the saved token has insecure TLS (same scope as above; dev only). |
257
260
 
261
+ ### Stateless token mode
262
+
263
+ Pass an access token via `--token` for fully stateless invocations (no read or write of `~/.kweaver/` for that token):
264
+
265
+ ```bash
266
+ kweaver --base-url https://platform.example.com --token "$TOK" bkn list
267
+ ```
268
+
269
+ Resolution order:
270
+
271
+ | Source | base-url | token |
272
+ |--------|----------|-------|
273
+ | flag | `--base-url` | `--token` |
274
+ | env | `KWEAVER_BASE_URL` | `KWEAVER_TOKEN` |
275
+ | disk | active platform | OAuth session (refreshable) |
276
+
277
+ When `--token` is used, write-disk commands (`auth login` / `logout` / `use` / `delete` / `switch`, `config set-bd`, the entire `context-loader config` group) error out — drop `--token` or use `kweaver auth login` for a saved session.
278
+
279
+ `auth whoami` / `auth status` distinguish the two stateless modes: `Source: CLI (flag: --token)` for flag mode, `env (KWEAVER_TOKEN)` for env mode (`whoami --json` uses `"source": "flag"` vs `"source": "env"`).
280
+
281
+ `kweaver context-loader` runtime subcommands accept `<kn-id>` as the first positional (e.g. `kweaver context-loader tools <kn-id>`) or via the global `--kn-id <id>` / `-k <id>` flag, so they work in stateless mode without any saved config. The `context-loader config set|use|list|remove|show` management group is deprecated, prints a warning on use, and is disabled in its entirety under `--token`.
282
+
258
283
  ### TLS Certificate Troubleshooting
259
284
 
260
285
  If you encounter errors like `fetch failed`, `self-signed certificate`, or `UNABLE_TO_GET_ISSUER_CERT`, the target server likely uses a self-signed certificate or Kubernetes Ingress default fake certificate. Try the following in order of preference:
package/README.zh.md CHANGED
@@ -176,8 +176,10 @@ kweaver bkn action-log list/get/cancel
176
176
  kweaver agent list/get/chat/sessions/history
177
177
  kweaver skill list/market/get/register/status/delete/content/read-file/download/install
178
178
  kweaver vega health|stats|inspect|sql|catalog|resource|connector-type
179
- kweaver context-loader config set/use/list/show
180
- kweaver context-loader search-schema/tool-call/kn-search/query-object-instance/find-skills/...
179
+ kweaver context-loader tools|resources|templates|prompts <kn-id>
180
+ kweaver context-loader search-schema|tool-call|kn-search|kn-schema-search <kn-id> <query|name> [...]
181
+ kweaver context-loader query-object-instance|query-instance-subgraph|get-logic-properties|get-action-info|find-skills <kn-id> ...
182
+ kweaver context-loader config set/use/list/show (deprecated;省略 <kn-id> 时回退到已保存配置)
181
183
  kweaver call <path> [-X METHOD] [-d BODY] [-H header]
182
184
  ```
183
185
 
@@ -218,10 +220,33 @@ kweaver vega sql -d '{"resource_type":"mysql","query":"SELECT * FROM {{res-1}} L
218
220
  | `KWEAVER_BASE_URL` | KWeaver 实例地址 |
219
221
  | `KWEAVER_BUSINESS_DOMAIN` | 业务域标识 |
220
222
  | `KWEAVER_TOKEN` | 访问令牌 |
223
+ | `KWEAVER_TOKEN_SOURCE` | CLI 传入 `--token` 时由程序设置的内部标记;请勿手动设置 |
221
224
  | `KWEAVER_NO_AUTH` | 设为 `1`/`true`/`yes` 且未设置 `KWEAVER_TOKEN` 时使用 no-auth 占位(需 `KWEAVER_BASE_URL` 或已选平台) |
222
225
  | `KWEAVER_TLS_INSECURE` | 设为 `1` 或 `true` 时跳过 TLS 证书校验(仅开发;更推荐 `kweaver auth … --insecure` 以按平台持久化) |
223
226
  | `NODE_TLS_REJECT_UNAUTHORIZED` | Node.js 内置 TLS 开关:设为 `0` 时在本进程内跳过 HTTPS 证书校验。`kweaver` 在 `KWEAVER_TLS_INSECURE` 生效或已保存 token 为不安全 TLS 时会设置此项(范围同上;仅开发)。 |
224
227
 
228
+ ### Stateless token 模式
229
+
230
+ 通过 `--token` 传入访问令牌,该次调用对该 token 路径既不读也不写 `~/.kweaver/`:
231
+
232
+ ```bash
233
+ kweaver --base-url https://platform.example.com --token "$TOK" bkn list
234
+ ```
235
+
236
+ 来源优先级:
237
+
238
+ | 来源 | base-url | token |
239
+ |------|----------|-------|
240
+ | flag | `--base-url` | `--token` |
241
+ | env | `KWEAVER_BASE_URL` | `KWEAVER_TOKEN` |
242
+ | 磁盘 | active platform | OAuth 会话(可 refresh) |
243
+
244
+ `--token` 模式下会禁用写盘命令:`auth login` / `logout` / `use` / `delete` / `switch`、`config set-bd`、整个 `context-loader config` 子命令组 ——去掉 `--token` 或改用 `kweaver auth login`。
245
+
246
+ `auth whoami` / `auth status` 通过文案区分来源:flag 模式为 `CLI (flag: --token)`,env 模式为 `env (KWEAVER_TOKEN)`(`whoami --json` 为 `"source": "flag"` 与 `"source": "env"`)。
247
+
248
+ `kweaver context-loader` 运行时子命令将 `<kn-id>` 作为第一个位置参数(如 `kweaver context-loader tools <kn-id>`),也支持全局 `--kn-id <id>` / `-k <id>` flag,因此在 stateless 模式下可直接使用,无需任何持久化配置。`context-loader config set|use|list|remove|show` 管理子命令已被标记为 deprecated(每次调用打印警告),且在 `--token` 下整组被禁用。
249
+
225
250
  ### TLS 证书问题排查
226
251
 
227
252
  如果遇到 `fetch failed`、`self-signed certificate`、`UNABLE_TO_GET_ISSUER_CERT` 等 TLS 相关错误,通常是目标服务器使用了自签名证书或 Kubernetes Ingress 默认假证书。可按优先级尝试以下方案:
@@ -103,18 +103,20 @@ export async function updateSkillStatus(options) {
103
103
  }
104
104
  export async function registerSkillContent(options) {
105
105
  const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills`);
106
- const payload = {
107
- file_type: "content",
108
- file: options.content,
109
- };
106
+ const form = new FormData();
107
+ form.set("file_type", "content");
108
+ // Backend's gin form-binder rejects plain string field for `file`
109
+ // (typed json.RawMessage); needs an actual multipart file part with
110
+ // filename. See utils/gin.go GetBindMultipartFormRaw.
111
+ form.set("file", new Blob([options.content], { type: "text/markdown" }), "SKILL.md");
110
112
  if (options.source)
111
- payload.source = options.source;
113
+ form.set("source", options.source);
112
114
  if (options.extendInfo)
113
- payload.extend_info = options.extendInfo;
115
+ form.set("extend_info", JSON.stringify(options.extendInfo));
114
116
  const { body } = await fetchTextOrThrow(url, {
115
117
  method: "POST",
116
- headers: { ...baseHeaders(options), "content-type": "application/json" },
117
- body: JSON.stringify(payload),
118
+ headers: baseHeaders(options),
119
+ body: form,
118
120
  });
119
121
  return normalizeSkillId(unwrapEnvelope(body));
120
122
  }
package/dist/cli.js CHANGED
@@ -19,7 +19,7 @@ function printHelp() {
19
19
  console.log(`kweaver
20
20
 
21
21
  Usage:
22
- kweaver [--user <userId|username>] <command> [options]
22
+ kweaver [--base-url <url>] [--token <access-token>] [--user <userId|username>] <command> [options]
23
23
  kweaver --version | -V
24
24
  kweaver --help | -h
25
25
 
@@ -60,6 +60,7 @@ Usage:
60
60
  kweaver ds delete <id> [-y]
61
61
  kweaver ds tables <id> [--keyword X]
62
62
  kweaver ds connect <db_type> <host> <port> <database> --account X --password Y [--schema S] [--name N]
63
+ [--reuse-existing|--force-new]
63
64
 
64
65
  kweaver dataflow list [-bd value]
65
66
  kweaver dataflow run <dagId> (--file <path> | --url <remote-url> --name <filename>) [-bd value]
@@ -123,18 +124,21 @@ Usage:
123
124
  kweaver vega query execute|sql [options]
124
125
  kweaver vega connector-type list|get [options]
125
126
 
126
- kweaver context-loader config set|use|list|remove|show [options]
127
- kweaver context-loader tools|resources|templates|prompts [--cursor]
128
- kweaver context-loader resource <uri>
129
- kweaver context-loader prompt <name> [--args json]
130
- kweaver context-loader search-schema <query> [--scope object,relation,action,metric] [--max N]
131
- kweaver context-loader tool-call <name> --args '<json>'
132
- kweaver context-loader kn-search <query> [--only-schema] (compat HTTP)
133
- kweaver context-loader kn-schema-search <query> [--max N] (compat HTTP)
134
- kweaver context-loader query-object-instance|query-instance-subgraph|get-logic-properties|get-action-info|find-skills ...
127
+ kweaver context-loader config set|use|list|remove|show [options] (deprecated; not supported with --token)
128
+ kweaver context-loader tools|resources|templates|prompts <kn-id> [--cursor]
129
+ kweaver context-loader resource <kn-id> <uri>
130
+ kweaver context-loader prompt <kn-id> <name> [--args json]
131
+ kweaver context-loader search-schema <kn-id> <query> [--scope object,relation,action,metric] [--max N]
132
+ kweaver context-loader tool-call <kn-id> <name> --args '<json>'
133
+ kweaver context-loader kn-search <kn-id> <query> [--only-schema] (compat HTTP)
134
+ kweaver context-loader kn-schema-search <kn-id> <query> [--max N] (compat HTTP)
135
+ kweaver context-loader query-object-instance|query-instance-subgraph|get-logic-properties|get-action-info|find-skills <kn-id> ...
136
+ (omit <kn-id> to fall back to deprecated saved config)
135
137
  (alias: kweaver context ...)
136
138
 
137
139
  Global options:
140
+ --base-url <url> Override platform base URL for this command (env: KWEAVER_BASE_URL)
141
+ --token <value> Override access token for this command (env: KWEAVER_TOKEN; disables write-to-disk commands)
138
142
  --user <id|name> Use a specific user's credentials for this command (env: KWEAVER_USER)
139
143
  --pretty / --compact
140
144
  Toggle pretty-printed JSON output. Supported by every
@@ -165,12 +169,40 @@ export async function run(argv) {
165
169
  !process.env.KWEAVER_TOKEN) {
166
170
  process.env.KWEAVER_TOKEN = NO_AUTH_TOKEN;
167
171
  }
168
- // Global --user flag: override active user for this invocation
169
- const userIdx = argv.indexOf("--user");
172
+ // Global flags consumed before subcommand dispatch.
173
+ // Pattern follows --user (legacy): each flag, if present, is removed from argv
174
+ // and projected into a process.env value that downstream resolvers already read.
170
175
  let filteredArgv = argv;
171
- if (userIdx !== -1 && userIdx + 1 < argv.length) {
172
- process.env.KWEAVER_USER = argv[userIdx + 1];
173
- filteredArgv = [...argv.slice(0, userIdx), ...argv.slice(userIdx + 2)];
176
+ function consumeFlag(flag) {
177
+ const idx = filteredArgv.indexOf(flag);
178
+ if (idx === -1 || idx + 1 >= filteredArgv.length)
179
+ return undefined;
180
+ const value = filteredArgv[idx + 1];
181
+ filteredArgv = [...filteredArgv.slice(0, idx), ...filteredArgv.slice(idx + 2)];
182
+ return value;
183
+ }
184
+ const userVal = consumeFlag("--user");
185
+ if (userVal)
186
+ process.env.KWEAVER_USER = userVal;
187
+ const tokenVal = consumeFlag("--token");
188
+ const baseUrlVal = consumeFlag("--base-url");
189
+ if (tokenVal) {
190
+ process.env.KWEAVER_TOKEN = tokenVal;
191
+ process.env.KWEAVER_TOKEN_SOURCE = "flag";
192
+ }
193
+ if (baseUrlVal) {
194
+ process.env.KWEAVER_BASE_URL = baseUrlVal;
195
+ }
196
+ // --token requires a base URL from somewhere; fail fast with guidance.
197
+ if (tokenVal && !process.env.KWEAVER_BASE_URL) {
198
+ const { getCurrentPlatform } = await import("./config/store.js");
199
+ if (!getCurrentPlatform()) {
200
+ console.error("--token requires a base URL. Provide one of:\n" +
201
+ " --base-url <url>\n" +
202
+ " export KWEAVER_BASE_URL=<url>\n" +
203
+ " kweaver auth login <url> (save once, reuse later)");
204
+ return 1;
205
+ }
174
206
  }
175
207
  const [command, ...rest] = filteredArgv;
176
208
  if (command === "--version" || command === "-V" || command === "version") {
@@ -1,4 +1,5 @@
1
1
  import { isNoAuth } from "../config/no-auth.js";
2
+ import { assertNotStatelessForWrite } from "../config/stateless.js";
2
3
  import { autoSelectBusinessDomain, clearPlatformSession, deletePlatform, deleteUser, getActiveUser, getConfigDir, getCurrentPlatform, getPlatformAlias, hasPlatform, listPlatforms, listUserProfiles, loadClientConfig, loadTokenConfig, loadUserTokenConfig, resolveBusinessDomain, resolvePlatformIdentifier, resolveUserId, saveNoAuthPlatform, setActiveUser, setCurrentPlatform, setPlatformAlias, } from "../config/store.js";
3
4
  import { decodeJwtPayload } from "../config/jwt.js";
4
5
  import { eacpModifyPassword } from "../auth/eacp-modify-password.js";
@@ -71,6 +72,13 @@ Login options:
71
72
  const LOGIN_SUBCOMMANDS = new Set(["status", "list", "use", "delete", "logout", "export", "whoami", "users", "switch"]);
72
73
  if (target && !LOGIN_SUBCOMMANDS.has(target)) {
73
74
  try {
75
+ try {
76
+ assertNotStatelessForWrite("auth login");
77
+ }
78
+ catch (err) {
79
+ console.error(err instanceof Error ? err.message : String(err));
80
+ return 1;
81
+ }
74
82
  const normalizedTarget = normalizeBaseUrl(target);
75
83
  const alias = readOption(args, "--alias");
76
84
  let username = readOption(args, "--username") ?? readOption(args, "-u");
@@ -268,7 +276,8 @@ Login options:
268
276
  }
269
277
  console.log(`Config directory: ${getConfigDir()}`);
270
278
  console.log(`Platform: ${active.url} (KWEAVER_BASE_URL)`);
271
- console.log(`Token present: yes (KWEAVER_TOKEN)`);
279
+ const tokenProvenance = process.env.KWEAVER_TOKEN_SOURCE === "flag" ? "CLI (flag: --token)" : "KWEAVER_TOKEN";
280
+ console.log(`Token present: yes (${tokenProvenance})`);
272
281
  console.log(`Refresh token: n/a (env)`);
273
282
  return 0;
274
283
  }
@@ -358,6 +367,13 @@ Login options:
358
367
  console.error(`No saved token for ${useTarget}. Run \`kweaver auth login ${useTarget}\` first.`);
359
368
  return 1;
360
369
  }
370
+ try {
371
+ assertNotStatelessForWrite("auth use");
372
+ }
373
+ catch (err) {
374
+ console.error(err instanceof Error ? err.message : String(err));
375
+ return 1;
376
+ }
361
377
  setCurrentPlatform(useTarget);
362
378
  console.log(`Current platform: ${useTarget}`);
363
379
  return 0;
@@ -375,6 +391,13 @@ Login options:
375
391
  console.error(`No saved token for ${deleteTarget}.`);
376
392
  return 1;
377
393
  }
394
+ try {
395
+ assertNotStatelessForWrite("auth delete");
396
+ }
397
+ catch (err) {
398
+ console.error(err instanceof Error ? err.message : String(err));
399
+ return 1;
400
+ }
378
401
  if (deleteUserArg) {
379
402
  const deleteUserId = resolveUserId(deleteTarget, deleteUserArg) ?? deleteUserArg;
380
403
  deleteUser(deleteTarget, deleteUserId);
@@ -404,6 +427,13 @@ Login options:
404
427
  console.error(`No saved token for ${logoutTarget}.`);
405
428
  return 1;
406
429
  }
430
+ try {
431
+ assertNotStatelessForWrite("auth logout");
432
+ }
433
+ catch (err) {
434
+ console.error(err instanceof Error ? err.message : String(err));
435
+ return 1;
436
+ }
407
437
  const logoutUserId = logoutUserArg ? resolveUserId(logoutTarget, logoutUserArg) ?? logoutUserArg : undefined;
408
438
  clearPlatformSession(logoutTarget, logoutUserId);
409
439
  const userHint = logoutUserId ? ` (user: ${logoutUserId})` : "";
@@ -487,6 +517,13 @@ You can specify either the userId (sub claim) or the username (preferred_usernam
487
517
  }
488
518
  return 1;
489
519
  }
520
+ try {
521
+ assertNotStatelessForWrite("auth switch");
522
+ }
523
+ catch (err) {
524
+ console.error(err instanceof Error ? err.message : String(err));
525
+ return 1;
526
+ }
490
527
  setActiveUser(platform, resolvedId);
491
528
  const profiles = listUserProfiles(platform);
492
529
  const profile = profiles.find((p) => p.userId === resolvedId);
@@ -535,7 +572,10 @@ Options:
535
572
  // complete picture without forcing them to pick a mode.
536
573
  const jwtPayload = decodeJwtPayload(accessToken);
537
574
  if (jsonOutput) {
538
- const out = { platform: envUrl, source: "env" };
575
+ const out = {
576
+ platform: envUrl,
577
+ source: process.env.KWEAVER_TOKEN_SOURCE === "flag" ? "flag" : "env",
578
+ };
539
579
  if (userInfo)
540
580
  out.userInfo = userInfo;
541
581
  if (jwtPayload)
@@ -544,7 +584,7 @@ Options:
544
584
  return 0;
545
585
  }
546
586
  console.log(`Platform: ${envUrl}`);
547
- console.log(`Source: env (KWEAVER_TOKEN)`);
587
+ console.log(`Source: ${process.env.KWEAVER_TOKEN_SOURCE === "flag" ? "CLI (flag: --token)" : "env (KWEAVER_TOKEN)"}`);
548
588
  if (userInfo) {
549
589
  console.log(`Type: ${userInfo.type}`);
550
590
  console.log(`User ID: ${userInfo.id}`);
@@ -1,4 +1,6 @@
1
1
  import { type BknEncodingImportOptions } from "../utils/bkn-encoding.js";
2
+ export declare const BKN_OBJECT_NAME_MAX_LENGTH = 40;
3
+ export declare function assertValidBknObjectNames(names: string[], context: string): void;
2
4
  export declare function parseKnBuildArgs(args: string[]): {
3
5
  knId: string;
4
6
  wait: boolean;
@@ -34,6 +36,7 @@ export declare function parseKnCreateFromDsArgs(args: string[]): {
34
36
  timeout: number;
35
37
  businessDomain: string;
36
38
  pretty: boolean;
39
+ noRollback: boolean;
37
40
  };
38
41
  /** Generate a BKN ObjectType YAML markdown file for a table. */
39
42
  export declare function generateObjectTypeBkn(tableName: string, dvId: string, pk: string, dk: string, columns: Array<{
@@ -52,6 +55,7 @@ export declare function parseKnCreateFromCsvArgs(args: string[]): {
52
55
  recreate: boolean;
53
56
  timeout: number;
54
57
  businessDomain: string;
58
+ noRollback: boolean;
55
59
  };
56
60
  export declare function runKnCreateFromCsvCommand(args: string[]): Promise<number>;
57
61
  export interface ActionScheduleParsed {