@kweaver-ai/kweaver-sdk 0.5.2 → 0.6.0
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 +19 -1
- package/README.zh.md +19 -1
- package/dist/api/agent-chat.d.ts +7 -1
- package/dist/api/agent-chat.js +146 -40
- package/dist/api/agent-list.js +13 -13
- package/dist/api/business-domains.js +9 -5
- package/dist/api/context-loader.js +4 -1
- package/dist/api/conversations.js +4 -9
- package/dist/api/dataflow2.d.ts +95 -0
- package/dist/api/dataflow2.js +80 -0
- package/dist/api/headers.d.ts +2 -0
- package/dist/api/headers.js +7 -2
- package/dist/api/skills.js +2 -10
- package/dist/api/vega.d.ts +0 -16
- package/dist/api/vega.js +0 -33
- package/dist/auth/oauth.d.ts +1 -1
- package/dist/auth/oauth.js +64 -7
- package/dist/cli.js +21 -1
- package/dist/client.d.ts +9 -0
- package/dist/client.js +48 -8
- package/dist/commands/auth.js +80 -32
- package/dist/commands/bkn-schema.js +22 -0
- package/dist/commands/call.js +8 -5
- package/dist/commands/dataflow.d.ts +1 -0
- package/dist/commands/dataflow.js +251 -0
- package/dist/commands/explore-bkn.d.ts +79 -0
- package/dist/commands/explore-bkn.js +273 -0
- package/dist/commands/explore-chat.d.ts +3 -0
- package/dist/commands/explore-chat.js +193 -0
- package/dist/commands/explore-vega.d.ts +3 -0
- package/dist/commands/explore-vega.js +71 -0
- package/dist/commands/explore.d.ts +9 -0
- package/dist/commands/explore.js +258 -0
- package/dist/commands/vega.js +2 -104
- package/dist/config/no-auth.d.ts +3 -0
- package/dist/config/no-auth.js +5 -0
- package/dist/config/store.d.ts +8 -0
- package/dist/config/store.js +22 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/kweaver.d.ts +5 -0
- package/dist/kweaver.js +32 -2
- package/dist/resources/bkn.js +2 -3
- package/dist/resources/knowledge-networks.js +3 -8
- package/dist/resources/vega.d.ts +0 -6
- package/dist/resources/vega.js +1 -10
- package/dist/templates/explorer/app.js +136 -0
- package/dist/templates/explorer/bkn.js +747 -0
- package/dist/templates/explorer/chat.js +980 -0
- package/dist/templates/explorer/dashboard.js +82 -0
- package/dist/templates/explorer/index.html +35 -0
- package/dist/templates/explorer/style.css +2440 -0
- package/dist/templates/explorer/vega.js +291 -0
- package/dist/utils/http.d.ts +3 -0
- package/dist/utils/http.js +37 -1
- package/package.json +9 -5
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export interface DataflowListItem {
|
|
2
|
+
id: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
status?: string;
|
|
5
|
+
trigger?: string;
|
|
6
|
+
creator?: string;
|
|
7
|
+
updated_at?: number;
|
|
8
|
+
version_id?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DataflowListResponse {
|
|
11
|
+
dags: DataflowListItem[];
|
|
12
|
+
limit?: number;
|
|
13
|
+
page?: number;
|
|
14
|
+
total?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface DataflowRunSource {
|
|
17
|
+
name?: string;
|
|
18
|
+
content_type?: string;
|
|
19
|
+
size?: number;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export interface DataflowRunItem {
|
|
23
|
+
id: string;
|
|
24
|
+
status?: string;
|
|
25
|
+
started_at?: number;
|
|
26
|
+
ended_at?: number | null;
|
|
27
|
+
reason?: string | null;
|
|
28
|
+
source?: DataflowRunSource;
|
|
29
|
+
}
|
|
30
|
+
export interface DataflowRunsResponse {
|
|
31
|
+
results: DataflowRunItem[];
|
|
32
|
+
limit?: number;
|
|
33
|
+
page?: number;
|
|
34
|
+
total?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface DataflowLogMetadata {
|
|
37
|
+
duration?: number;
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
}
|
|
40
|
+
export interface DataflowLogItem {
|
|
41
|
+
id: string;
|
|
42
|
+
operator?: string;
|
|
43
|
+
status?: string;
|
|
44
|
+
started_at?: number;
|
|
45
|
+
updated_at?: number;
|
|
46
|
+
inputs?: unknown;
|
|
47
|
+
outputs?: unknown;
|
|
48
|
+
taskId?: string;
|
|
49
|
+
metadata?: DataflowLogMetadata;
|
|
50
|
+
}
|
|
51
|
+
export interface DataflowLogsResponse {
|
|
52
|
+
results: DataflowLogItem[];
|
|
53
|
+
limit?: number;
|
|
54
|
+
page?: number;
|
|
55
|
+
total?: number;
|
|
56
|
+
}
|
|
57
|
+
export interface DataflowRunResponse {
|
|
58
|
+
dag_instance_id: string;
|
|
59
|
+
}
|
|
60
|
+
interface BaseOptions {
|
|
61
|
+
baseUrl: string;
|
|
62
|
+
accessToken: string;
|
|
63
|
+
businessDomain?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface RunDataflowWithFileOptions extends BaseOptions {
|
|
66
|
+
dagId: string;
|
|
67
|
+
fileName: string;
|
|
68
|
+
fileBytes: Uint8Array;
|
|
69
|
+
}
|
|
70
|
+
export interface RunDataflowWithRemoteUrlOptions extends BaseOptions {
|
|
71
|
+
dagId: string;
|
|
72
|
+
url: string;
|
|
73
|
+
name: string;
|
|
74
|
+
}
|
|
75
|
+
export interface ListDataflowRunsOptions extends BaseOptions {
|
|
76
|
+
dagId: string;
|
|
77
|
+
page?: number;
|
|
78
|
+
limit?: number;
|
|
79
|
+
sortBy?: string;
|
|
80
|
+
order?: string;
|
|
81
|
+
startTime?: number;
|
|
82
|
+
endTime?: number;
|
|
83
|
+
}
|
|
84
|
+
export interface GetDataflowLogsPageOptions extends BaseOptions {
|
|
85
|
+
dagId: string;
|
|
86
|
+
instanceId: string;
|
|
87
|
+
page: number;
|
|
88
|
+
limit?: number;
|
|
89
|
+
}
|
|
90
|
+
export declare function listDataflows(options: BaseOptions): Promise<DataflowListResponse>;
|
|
91
|
+
export declare function runDataflowWithFile(options: RunDataflowWithFileOptions): Promise<DataflowRunResponse>;
|
|
92
|
+
export declare function runDataflowWithRemoteUrl(options: RunDataflowWithRemoteUrlOptions): Promise<DataflowRunResponse>;
|
|
93
|
+
export declare function listDataflowRuns(options: ListDataflowRunsOptions): Promise<DataflowRunsResponse>;
|
|
94
|
+
export declare function getDataflowLogsPage(options: GetDataflowLogsPageOptions): Promise<DataflowLogsResponse>;
|
|
95
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { HttpError } from "../utils/http.js";
|
|
2
|
+
import { buildHeaders } from "./headers.js";
|
|
3
|
+
async function parseJsonOrThrow(response) {
|
|
4
|
+
const body = await response.text();
|
|
5
|
+
if (!response.ok) {
|
|
6
|
+
throw new HttpError(response.status, response.statusText, body);
|
|
7
|
+
}
|
|
8
|
+
return JSON.parse(body);
|
|
9
|
+
}
|
|
10
|
+
export async function listDataflows(options) {
|
|
11
|
+
const { baseUrl, accessToken, businessDomain = "bd_public" } = options;
|
|
12
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
13
|
+
const url = `${base}/api/automation/v2/dags?type=data-flow&page=0&limit=-1`;
|
|
14
|
+
const response = await fetch(url, {
|
|
15
|
+
method: "GET",
|
|
16
|
+
headers: buildHeaders(accessToken, businessDomain),
|
|
17
|
+
});
|
|
18
|
+
return parseJsonOrThrow(response);
|
|
19
|
+
}
|
|
20
|
+
export async function runDataflowWithFile(options) {
|
|
21
|
+
const { baseUrl, accessToken, businessDomain = "bd_public", dagId, fileName, fileBytes } = options;
|
|
22
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
23
|
+
const url = `${base}/api/automation/v2/dataflow-doc/trigger/${encodeURIComponent(dagId)}`;
|
|
24
|
+
const form = new FormData();
|
|
25
|
+
form.set("file", new Blob([fileBytes]), fileName);
|
|
26
|
+
const response = await fetch(url, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: buildHeaders(accessToken, businessDomain),
|
|
29
|
+
body: form,
|
|
30
|
+
});
|
|
31
|
+
return parseJsonOrThrow(response);
|
|
32
|
+
}
|
|
33
|
+
export async function runDataflowWithRemoteUrl(options) {
|
|
34
|
+
const { baseUrl, accessToken, businessDomain = "bd_public", dagId, url, name } = options;
|
|
35
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
36
|
+
const endpoint = `${base}/api/automation/v2/dataflow-doc/trigger/${encodeURIComponent(dagId)}`;
|
|
37
|
+
const response = await fetch(endpoint, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: {
|
|
40
|
+
...buildHeaders(accessToken, businessDomain),
|
|
41
|
+
"content-type": "application/json",
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify({
|
|
44
|
+
source_from: "remote",
|
|
45
|
+
url,
|
|
46
|
+
name,
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
return parseJsonOrThrow(response);
|
|
50
|
+
}
|
|
51
|
+
export async function listDataflowRuns(options) {
|
|
52
|
+
const { baseUrl, accessToken, businessDomain = "bd_public", dagId, page = 0, limit = 100, sortBy, order, startTime, endTime, } = options;
|
|
53
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
54
|
+
const url = new URL(`${base}/api/automation/v2/dag/${encodeURIComponent(dagId)}/results`);
|
|
55
|
+
url.searchParams.set("page", String(page));
|
|
56
|
+
url.searchParams.set("limit", String(limit));
|
|
57
|
+
if (sortBy)
|
|
58
|
+
url.searchParams.set("sortBy", sortBy);
|
|
59
|
+
if (order)
|
|
60
|
+
url.searchParams.set("order", order);
|
|
61
|
+
if (startTime != null)
|
|
62
|
+
url.searchParams.set("start_time", String(startTime));
|
|
63
|
+
if (endTime != null)
|
|
64
|
+
url.searchParams.set("end_time", String(endTime));
|
|
65
|
+
const response = await fetch(url.toString(), {
|
|
66
|
+
method: "GET",
|
|
67
|
+
headers: buildHeaders(accessToken, businessDomain),
|
|
68
|
+
});
|
|
69
|
+
return parseJsonOrThrow(response);
|
|
70
|
+
}
|
|
71
|
+
export async function getDataflowLogsPage(options) {
|
|
72
|
+
const { baseUrl, accessToken, businessDomain = "bd_public", dagId, instanceId, page, limit = 10 } = options;
|
|
73
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
74
|
+
const url = `${base}/api/automation/v2/dag/${encodeURIComponent(dagId)}/result/${encodeURIComponent(instanceId)}?page=${page}&limit=${limit}`;
|
|
75
|
+
const response = await fetch(url, {
|
|
76
|
+
method: "GET",
|
|
77
|
+
headers: buildHeaders(accessToken, businessDomain),
|
|
78
|
+
});
|
|
79
|
+
return parseJsonOrThrow(response);
|
|
80
|
+
}
|
package/dist/api/headers.d.ts
CHANGED
|
@@ -5,5 +5,7 @@
|
|
|
5
5
|
* environment variables KWEAVER_ACCOUNT_ID and KWEAVER_ACCOUNT_TYPE.
|
|
6
6
|
* These are required by older platform versions (e.g. dip-poc.aishu.cn)
|
|
7
7
|
* that do not infer account info from the token automatically.
|
|
8
|
+
*
|
|
9
|
+
* When accessToken is the no-auth sentinel, `authorization` and `token` are omitted.
|
|
8
10
|
*/
|
|
9
11
|
export declare function buildHeaders(accessToken: string, businessDomain: string): Record<string, string>;
|
package/dist/api/headers.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isNoAuth } from "../config/no-auth.js";
|
|
1
2
|
/**
|
|
2
3
|
* Shared HTTP header builder for all KWeaver API calls.
|
|
3
4
|
*
|
|
@@ -5,16 +6,20 @@
|
|
|
5
6
|
* environment variables KWEAVER_ACCOUNT_ID and KWEAVER_ACCOUNT_TYPE.
|
|
6
7
|
* These are required by older platform versions (e.g. dip-poc.aishu.cn)
|
|
7
8
|
* that do not infer account info from the token automatically.
|
|
9
|
+
*
|
|
10
|
+
* When accessToken is the no-auth sentinel, `authorization` and `token` are omitted.
|
|
8
11
|
*/
|
|
9
12
|
export function buildHeaders(accessToken, businessDomain) {
|
|
10
13
|
const headers = {
|
|
11
14
|
accept: "application/json, text/plain, */*",
|
|
12
15
|
"accept-language": "zh-cn",
|
|
13
|
-
authorization: `Bearer ${accessToken}`,
|
|
14
|
-
token: accessToken,
|
|
15
16
|
"x-business-domain": businessDomain,
|
|
16
17
|
"x-language": "zh-cn",
|
|
17
18
|
};
|
|
19
|
+
if (!isNoAuth(accessToken)) {
|
|
20
|
+
headers.authorization = `Bearer ${accessToken}`;
|
|
21
|
+
headers.token = accessToken;
|
|
22
|
+
}
|
|
18
23
|
const accountId = process.env.KWEAVER_ACCOUNT_ID;
|
|
19
24
|
const accountType = process.env.KWEAVER_ACCOUNT_TYPE;
|
|
20
25
|
if (accountId)
|
package/dist/api/skills.js
CHANGED
|
@@ -2,19 +2,11 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import { Buffer } from "node:buffer";
|
|
3
3
|
import { existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { basename, resolve } from "node:path";
|
|
5
|
+
import { buildHeaders as buildPlatformHeaders } from "./headers.js";
|
|
5
6
|
import { HttpError, fetchTextOrThrow } from "../utils/http.js";
|
|
6
7
|
const SKILL_API_PREFIX = "/api/agent-operator-integration/v1";
|
|
7
|
-
function buildHeaders(accessToken, businessDomain) {
|
|
8
|
-
return {
|
|
9
|
-
accept: "application/json, text/plain, */*",
|
|
10
|
-
authorization: `Bearer ${accessToken}`,
|
|
11
|
-
token: accessToken,
|
|
12
|
-
"x-business-domain": businessDomain,
|
|
13
|
-
"x-language": "zh-cn",
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
8
|
function baseHeaders(opts) {
|
|
17
|
-
return
|
|
9
|
+
return buildPlatformHeaders(opts.accessToken, opts.businessDomain ?? "bd_public");
|
|
18
10
|
}
|
|
19
11
|
function buildUrl(baseUrl, path) {
|
|
20
12
|
return `${baseUrl.replace(/\/+$/, "")}${path}`;
|
package/dist/api/vega.d.ts
CHANGED
|
@@ -165,15 +165,6 @@ export interface SetVegaConnectorTypeEnabledOptions {
|
|
|
165
165
|
businessDomain?: string;
|
|
166
166
|
}
|
|
167
167
|
export declare function setVegaConnectorTypeEnabled(options: SetVegaConnectorTypeEnabledOptions): Promise<string>;
|
|
168
|
-
export interface ListVegaDiscoverTasksOptions {
|
|
169
|
-
baseUrl: string;
|
|
170
|
-
accessToken: string;
|
|
171
|
-
status?: string;
|
|
172
|
-
limit?: number;
|
|
173
|
-
offset?: number;
|
|
174
|
-
businessDomain?: string;
|
|
175
|
-
}
|
|
176
|
-
export declare function listVegaDiscoverTasks(options: ListVegaDiscoverTasksOptions): Promise<string>;
|
|
177
168
|
export interface CreateVegaDatasetDocsOptions {
|
|
178
169
|
baseUrl: string;
|
|
179
170
|
accessToken: string;
|
|
@@ -237,10 +228,3 @@ export interface ListAllVegaResourcesOptions {
|
|
|
237
228
|
businessDomain?: string;
|
|
238
229
|
}
|
|
239
230
|
export declare function listAllVegaResources(options: ListAllVegaResourcesOptions): Promise<string>;
|
|
240
|
-
export interface GetVegaDiscoverTaskOptions {
|
|
241
|
-
baseUrl: string;
|
|
242
|
-
accessToken: string;
|
|
243
|
-
id: string;
|
|
244
|
-
businessDomain?: string;
|
|
245
|
-
}
|
|
246
|
-
export declare function getVegaDiscoverTask(options: GetVegaDiscoverTaskOptions): Promise<string>;
|
package/dist/api/vega.js
CHANGED
|
@@ -346,26 +346,6 @@ export async function setVegaConnectorTypeEnabled(options) {
|
|
|
346
346
|
throw new HttpError(response.status, response.statusText, body);
|
|
347
347
|
return body;
|
|
348
348
|
}
|
|
349
|
-
export async function listVegaDiscoverTasks(options) {
|
|
350
|
-
const { baseUrl, accessToken, status, limit, offset, businessDomain = "bd_public", } = options;
|
|
351
|
-
const base = baseUrl.replace(/\/+$/, "");
|
|
352
|
-
const url = new URL(`${base}${VEGA_BASE}/discover-tasks`);
|
|
353
|
-
if (status)
|
|
354
|
-
url.searchParams.set("status", status);
|
|
355
|
-
if (limit !== undefined)
|
|
356
|
-
url.searchParams.set("limit", String(limit));
|
|
357
|
-
if (offset !== undefined)
|
|
358
|
-
url.searchParams.set("offset", String(offset));
|
|
359
|
-
const response = await fetch(url.toString(), {
|
|
360
|
-
method: "GET",
|
|
361
|
-
headers: buildHeaders(accessToken, businessDomain),
|
|
362
|
-
});
|
|
363
|
-
const body = await response.text();
|
|
364
|
-
if (!response.ok) {
|
|
365
|
-
throw new HttpError(response.status, response.statusText, body);
|
|
366
|
-
}
|
|
367
|
-
return body;
|
|
368
|
-
}
|
|
369
349
|
export async function createVegaDatasetDocs(options) {
|
|
370
350
|
const { baseUrl, accessToken, id, body: requestBody, businessDomain = "bd_public" } = options;
|
|
371
351
|
const base = baseUrl.replace(/\/+$/, "");
|
|
@@ -495,16 +475,3 @@ export async function listAllVegaResources(options) {
|
|
|
495
475
|
throw new HttpError(response.status, response.statusText, body);
|
|
496
476
|
return body;
|
|
497
477
|
}
|
|
498
|
-
export async function getVegaDiscoverTask(options) {
|
|
499
|
-
const { baseUrl, accessToken, id, businessDomain = "bd_public" } = options;
|
|
500
|
-
const base = baseUrl.replace(/\/+$/, "");
|
|
501
|
-
const url = `${base}${VEGA_BASE}/discover-tasks/${encodeURIComponent(id)}`;
|
|
502
|
-
const response = await fetch(url, {
|
|
503
|
-
method: "GET",
|
|
504
|
-
headers: buildHeaders(accessToken, businessDomain),
|
|
505
|
-
});
|
|
506
|
-
const body = await response.text();
|
|
507
|
-
if (!response.ok)
|
|
508
|
-
throw new HttpError(response.status, response.statusText, body);
|
|
509
|
-
return body;
|
|
510
|
-
}
|
package/dist/auth/oauth.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare function normalizeBaseUrl(value: string): string;
|
|
|
21
21
|
*/
|
|
22
22
|
export declare function oauth2Login(baseUrl: string, options?: {
|
|
23
23
|
port?: number;
|
|
24
|
-
/** Full redirect URI override (e.g. "http://127.0.0.1:
|
|
24
|
+
/** Full redirect URI override (e.g. "http://127.0.0.1:9010/callback" or a remote URL). */
|
|
25
25
|
redirectUri?: string;
|
|
26
26
|
scope?: string;
|
|
27
27
|
clientId?: string;
|
package/dist/auth/oauth.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { isNoAuth } from "../config/no-auth.js";
|
|
2
|
+
import { deleteClientConfig, getCurrentPlatform, loadClientConfig, loadTokenConfig, loadUserTokenConfig, resolveUserId, saveClientConfig, saveNoAuthPlatform, saveTokenConfig, setCurrentPlatform, } from "../config/store.js";
|
|
3
|
+
import { HttpError, NetworkRequestError, fetchWithRetry } from "../utils/http.js";
|
|
3
4
|
const TOKEN_TTL_SECONDS = 3600;
|
|
4
5
|
/** Seconds before access token expiry to trigger refresh (matches Python ConfigAuth). */
|
|
5
6
|
const REFRESH_THRESHOLD_SEC = 60;
|
|
@@ -282,7 +283,17 @@ export async function oauth2Login(baseUrl, options) {
|
|
|
282
283
|
const listenPort = parsedRedirect?.port ?? port;
|
|
283
284
|
const callbackPathname = parsedRedirect?.pathname ?? "/callback";
|
|
284
285
|
// Step 1: Determine client — use provided client ID or fall back to dynamic registration
|
|
285
|
-
let client
|
|
286
|
+
let client;
|
|
287
|
+
try {
|
|
288
|
+
client = await resolveOrRegisterClient(base, redirectUri, scope, options);
|
|
289
|
+
}
|
|
290
|
+
catch (e) {
|
|
291
|
+
if (e instanceof HttpError && e.status === 404) {
|
|
292
|
+
process.stderr.write("OAuth2 endpoint not found (404). Saving platform in no-auth mode.\n");
|
|
293
|
+
return saveNoAuthPlatform(base, { tlsInsecure: options?.tlsInsecure });
|
|
294
|
+
}
|
|
295
|
+
throw e;
|
|
296
|
+
}
|
|
286
297
|
// Use PKCE when no client secret is available (public client / platform client).
|
|
287
298
|
const usePkce = !client.clientSecret;
|
|
288
299
|
const pkce = usePkce ? await generatePkce() : null;
|
|
@@ -515,7 +526,17 @@ export async function playwrightLogin(baseUrl, options) {
|
|
|
515
526
|
const callbackPathname = parsedRedirect?.pathname ?? "/callback";
|
|
516
527
|
const hasCredentials = !!(options?.username && options?.password);
|
|
517
528
|
// Step 1: Ensure registered OAuth2 client (with stale-client auto-recovery)
|
|
518
|
-
let client
|
|
529
|
+
let client;
|
|
530
|
+
try {
|
|
531
|
+
client = await resolveOrRegisterClient(base, redirectUri, scope);
|
|
532
|
+
}
|
|
533
|
+
catch (e) {
|
|
534
|
+
if (e instanceof HttpError && e.status === 404) {
|
|
535
|
+
process.stderr.write("OAuth2 endpoint not found (404). Saving platform in no-auth mode.\n");
|
|
536
|
+
return saveNoAuthPlatform(base, { tlsInsecure: options?.tlsInsecure });
|
|
537
|
+
}
|
|
538
|
+
throw e;
|
|
539
|
+
}
|
|
519
540
|
// Step 2: Generate CSRF state
|
|
520
541
|
const state = randomBytes(12).toString("hex");
|
|
521
542
|
// Step 3: Build authorization URL
|
|
@@ -676,6 +697,9 @@ export async function refreshTokenLogin(baseUrl, options) {
|
|
|
676
697
|
return token;
|
|
677
698
|
}
|
|
678
699
|
function tokenNeedsRefresh(token) {
|
|
700
|
+
if (isNoAuth(token.accessToken)) {
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
679
703
|
if (!token.expiresAt) {
|
|
680
704
|
return false;
|
|
681
705
|
}
|
|
@@ -692,6 +716,9 @@ function tokenNeedsRefresh(token) {
|
|
|
692
716
|
*/
|
|
693
717
|
export async function refreshAccessToken(token) {
|
|
694
718
|
const baseUrl = normalizeBaseUrl(token.baseUrl);
|
|
719
|
+
if (isNoAuth(token.accessToken)) {
|
|
720
|
+
throw new Error(`Cannot refresh no-auth session for ${baseUrl}.`);
|
|
721
|
+
}
|
|
695
722
|
const refreshToken = token.refreshToken?.trim();
|
|
696
723
|
if (!refreshToken) {
|
|
697
724
|
throw new Error(`Token expired and no refresh_token available for ${baseUrl}. Run \`kweaver auth login ${baseUrl}\` again.`);
|
|
@@ -710,7 +737,7 @@ export async function refreshAccessToken(token) {
|
|
|
710
737
|
});
|
|
711
738
|
let response;
|
|
712
739
|
try {
|
|
713
|
-
response = await runWithTlsInsecure(token.tlsInsecure, () =>
|
|
740
|
+
response = await runWithTlsInsecure(token.tlsInsecure, () => fetchWithRetry(url, {
|
|
714
741
|
method: "POST",
|
|
715
742
|
headers: {
|
|
716
743
|
Authorization: `Basic ${credentials}`,
|
|
@@ -777,11 +804,24 @@ export async function ensureValidToken(opts) {
|
|
|
777
804
|
return {
|
|
778
805
|
baseUrl: normalizeBaseUrl(envBaseUrl),
|
|
779
806
|
accessToken: rawToken,
|
|
780
|
-
tokenType: "bearer",
|
|
807
|
+
tokenType: isNoAuth(rawToken) ? "none" : "bearer",
|
|
781
808
|
scope: "",
|
|
782
809
|
obtainedAt: new Date().toISOString(),
|
|
783
810
|
};
|
|
784
811
|
}
|
|
812
|
+
if (!opts?.forceRefresh && envToken && !envBaseUrl) {
|
|
813
|
+
const currentPlatformForEnv = getCurrentPlatform();
|
|
814
|
+
if (currentPlatformForEnv) {
|
|
815
|
+
const rawToken = envToken.replace(/^Bearer\s+/i, "");
|
|
816
|
+
return {
|
|
817
|
+
baseUrl: normalizeBaseUrl(currentPlatformForEnv),
|
|
818
|
+
accessToken: rawToken,
|
|
819
|
+
tokenType: isNoAuth(rawToken) ? "none" : "bearer",
|
|
820
|
+
scope: "",
|
|
821
|
+
obtainedAt: new Date().toISOString(),
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
}
|
|
785
825
|
const currentPlatform = getCurrentPlatform();
|
|
786
826
|
if (!currentPlatform) {
|
|
787
827
|
throw new Error("No active platform selected. Run `kweaver auth login <platform-url>` first.");
|
|
@@ -803,6 +843,9 @@ export async function ensureValidToken(opts) {
|
|
|
803
843
|
if (!token) {
|
|
804
844
|
throw new Error(`No saved token for ${currentPlatform}. Run \`kweaver auth login ${currentPlatform}\` first.`);
|
|
805
845
|
}
|
|
846
|
+
if (isNoAuth(token.accessToken)) {
|
|
847
|
+
return token;
|
|
848
|
+
}
|
|
806
849
|
if (opts?.forceRefresh) {
|
|
807
850
|
return refreshAccessToken(token);
|
|
808
851
|
}
|
|
@@ -845,6 +888,9 @@ export async function with401RefreshRetry(fn) {
|
|
|
845
888
|
if (!latest) {
|
|
846
889
|
throw error;
|
|
847
890
|
}
|
|
891
|
+
if (isNoAuth(latest.accessToken)) {
|
|
892
|
+
throw error;
|
|
893
|
+
}
|
|
848
894
|
try {
|
|
849
895
|
await refreshAccessToken(latest);
|
|
850
896
|
}
|
|
@@ -869,6 +915,9 @@ export async function withTokenRetry(fn) {
|
|
|
869
915
|
}
|
|
870
916
|
catch (error) {
|
|
871
917
|
if (error instanceof HttpError && error.status === 401) {
|
|
918
|
+
if (isNoAuth(token.accessToken)) {
|
|
919
|
+
throw error;
|
|
920
|
+
}
|
|
872
921
|
const platformUrl = normalizeBaseUrl(token.baseUrl);
|
|
873
922
|
const envUser = process.env.KWEAVER_USER;
|
|
874
923
|
let latest;
|
|
@@ -918,6 +967,11 @@ function formatOAuthErrorBody(body) {
|
|
|
918
967
|
}
|
|
919
968
|
return lines.join("\n");
|
|
920
969
|
}
|
|
970
|
+
function isTlsVerificationDisabledForProcess() {
|
|
971
|
+
return (process.env.NODE_TLS_REJECT_UNAUTHORIZED === "0" ||
|
|
972
|
+
process.env.KWEAVER_TLS_INSECURE === "1" ||
|
|
973
|
+
process.env.KWEAVER_TLS_INSECURE === "true");
|
|
974
|
+
}
|
|
921
975
|
export function formatHttpError(error) {
|
|
922
976
|
if (error instanceof HttpError) {
|
|
923
977
|
const oauthMessage = formatOAuthErrorBody(error.body);
|
|
@@ -938,7 +992,10 @@ export function formatHttpError(error) {
|
|
|
938
992
|
if (error instanceof Error) {
|
|
939
993
|
const cause = "cause" in error && error.cause instanceof Error ? error.cause.message : "";
|
|
940
994
|
if (cause && error.message === "fetch failed") {
|
|
941
|
-
|
|
995
|
+
const hint = isTlsVerificationDisabledForProcess()
|
|
996
|
+
? "Hint: TLS verification is already disabled for this process. Check network reachability, TLS termination, or proxy stability."
|
|
997
|
+
: "Hint: use --insecure (-k) to skip TLS verification for self-signed certificates.";
|
|
998
|
+
return `${error.message}: ${cause}\n${hint}`;
|
|
942
999
|
}
|
|
943
1000
|
return error.message;
|
|
944
1001
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NO_AUTH_TOKEN } from "./config/no-auth.js";
|
|
1
2
|
import { applyTlsEnvFromSavedTokens } from "./config/tls-env.js";
|
|
2
3
|
import { runAgentCommand } from "./commands/agent.js";
|
|
3
4
|
import { runAuthCommand } from "./commands/auth.js";
|
|
@@ -5,7 +6,9 @@ import { runKnCommand } from "./commands/bkn.js";
|
|
|
5
6
|
import { runCallCommand } from "./commands/call.js";
|
|
6
7
|
import { runConfigCommand } from "./commands/config.js";
|
|
7
8
|
import { runContextLoaderCommand } from "./commands/context-loader.js";
|
|
9
|
+
import { runDataflowCommand } from "./commands/dataflow.js";
|
|
8
10
|
import { runDsCommand } from "./commands/ds.js";
|
|
11
|
+
import { runExploreCommand } from "./commands/explore.js";
|
|
9
12
|
import { runDataviewCommand } from "./commands/dataview.js";
|
|
10
13
|
import { runSkillCommand } from "./commands/skill.js";
|
|
11
14
|
import { runTokenCommand } from "./commands/token.js";
|
|
@@ -18,7 +21,7 @@ Usage:
|
|
|
18
21
|
kweaver --version | -V
|
|
19
22
|
kweaver --help | -h
|
|
20
23
|
|
|
21
|
-
kweaver auth <platform-url> [--alias name] [-u user] [-p pass] [--playwright] [--insecure|-k]
|
|
24
|
+
kweaver auth <platform-url> [--alias name] [--no-auth] [-u user] [-p pass] [--playwright] [--insecure|-k]
|
|
22
25
|
kweaver auth login <platform-url> (alias for auth <url>)
|
|
23
26
|
kweaver auth login <url> --client-id ID --client-secret S --refresh-token T (run on host without browser)
|
|
24
27
|
kweaver auth whoami [platform-url|alias] [--json]
|
|
@@ -55,6 +58,11 @@ Usage:
|
|
|
55
58
|
kweaver ds tables <id> [--keyword X] [--pretty]
|
|
56
59
|
kweaver ds connect <db_type> <host> <port> <database> --account X --password Y [--schema S] [--name N]
|
|
57
60
|
|
|
61
|
+
kweaver dataflow list [-bd value]
|
|
62
|
+
kweaver dataflow run <dagId> (--file <path> | --url <remote-url> --name <filename>) [-bd value]
|
|
63
|
+
kweaver dataflow runs <dagId> [--since <date-like>] [-bd value]
|
|
64
|
+
kweaver dataflow logs <dagId> <instanceId> [--detail] [-bd value]
|
|
65
|
+
|
|
58
66
|
kweaver dataview list [--datasource-id id] [--type atomic|custom] [--limit n] [-bd value] [--pretty]
|
|
59
67
|
kweaver dataview find --name <name> [--exact] [--datasource-id id] [--wait] [--timeout ms] [-bd value] [--pretty]
|
|
60
68
|
kweaver dataview get <id> [-bd value] [--pretty]
|
|
@@ -114,6 +122,7 @@ Commands:
|
|
|
114
122
|
call (curl) Call an API with curl-style flags and auto-injected token headers
|
|
115
123
|
agent Agent CRUD, chat, sessions, history, publish/unpublish
|
|
116
124
|
ds Manage datasources (list, get, delete, tables, connect)
|
|
125
|
+
dataflow Dataflow document workflows (list, run, runs, logs)
|
|
117
126
|
dataview|dv List, find, get, query (SQL), delete data views (atomic / custom)
|
|
118
127
|
bkn Knowledge network (CRUD, build, validate, export, stats, push/pull,
|
|
119
128
|
object-type, relation-type, subgraph, action-type, action-execution, action-log)
|
|
@@ -125,6 +134,11 @@ Commands:
|
|
|
125
134
|
}
|
|
126
135
|
export async function run(argv) {
|
|
127
136
|
applyTlsEnvFromSavedTokens();
|
|
137
|
+
const noAuthEnv = process.env.KWEAVER_NO_AUTH;
|
|
138
|
+
if ((noAuthEnv === "1" || noAuthEnv === "true" || noAuthEnv === "yes") &&
|
|
139
|
+
!process.env.KWEAVER_TOKEN) {
|
|
140
|
+
process.env.KWEAVER_TOKEN = NO_AUTH_TOKEN;
|
|
141
|
+
}
|
|
128
142
|
// Global --user flag: override active user for this invocation
|
|
129
143
|
const userIdx = argv.indexOf("--user");
|
|
130
144
|
let filteredArgv = argv;
|
|
@@ -153,6 +167,9 @@ export async function run(argv) {
|
|
|
153
167
|
if (command === "ds") {
|
|
154
168
|
return runDsCommand(rest);
|
|
155
169
|
}
|
|
170
|
+
if (command === "dataflow") {
|
|
171
|
+
return runDataflowCommand(rest);
|
|
172
|
+
}
|
|
156
173
|
if (command === "dataview" || command === "dv") {
|
|
157
174
|
return runDataviewCommand(rest);
|
|
158
175
|
}
|
|
@@ -162,6 +179,9 @@ export async function run(argv) {
|
|
|
162
179
|
if (command === "agent") {
|
|
163
180
|
return runAgentCommand(rest);
|
|
164
181
|
}
|
|
182
|
+
if (command === "explore") {
|
|
183
|
+
return runExploreCommand(rest);
|
|
184
|
+
}
|
|
165
185
|
if (command === "bkn") {
|
|
166
186
|
return runKnCommand(rest);
|
|
167
187
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -40,8 +40,17 @@ export interface KWeaverClientOptions {
|
|
|
40
40
|
* When true, read credentials exclusively from ~/.kweaver/ (saved by
|
|
41
41
|
* `kweaver auth login`), ignoring KWEAVER_BASE_URL / KWEAVER_TOKEN env vars.
|
|
42
42
|
* Useful when env vars hold stale tokens or are intended for other tooling.
|
|
43
|
+
* Incompatible with `auth: false` — the constructor throws if both are set.
|
|
43
44
|
*/
|
|
44
45
|
config?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* When false, use no-auth mode: API requests omit Authorization / token headers.
|
|
48
|
+
* Requires a resolvable base URL: `baseUrl`, `KWEAVER_BASE_URL`, or the active
|
|
49
|
+
* platform from `kweaver auth login`. Incompatible with `config: true` — use
|
|
50
|
+
* saved `~/.kweaver/` credentials (including `__NO_AUTH__`) via `config: true`
|
|
51
|
+
* alone instead of passing `auth: false`.
|
|
52
|
+
*/
|
|
53
|
+
auth?: boolean;
|
|
45
54
|
}
|
|
46
55
|
/**
|
|
47
56
|
* Main entry point for the KWeaver TypeScript SDK.
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { applyTlsEnvFromSavedTokens } from "./config/tls-env.js";
|
|
2
|
+
import { NO_AUTH_TOKEN, isNoAuth } from "./config/no-auth.js";
|
|
2
3
|
import { getCurrentPlatform, loadTokenConfig, } from "./config/store.js";
|
|
4
|
+
import { buildHeaders } from "./api/headers.js";
|
|
3
5
|
import { ensureValidToken } from "./auth/oauth.js";
|
|
4
6
|
import { AgentsResource } from "./resources/agents.js";
|
|
5
7
|
import { ConversationsResource } from "./resources/conversations.js";
|
|
@@ -64,8 +66,39 @@ export class KWeaverClient {
|
|
|
64
66
|
skills;
|
|
65
67
|
constructor(opts = {}) {
|
|
66
68
|
const envDomain = process.env.KWEAVER_BUSINESS_DOMAIN;
|
|
69
|
+
if (opts.auth === false && opts.config) {
|
|
70
|
+
throw new Error("KWeaverClient: auth: false is incompatible with config: true.");
|
|
71
|
+
}
|
|
67
72
|
let baseUrl;
|
|
68
73
|
let accessToken;
|
|
74
|
+
if (opts.auth === false) {
|
|
75
|
+
{
|
|
76
|
+
const envUrl = process.env.KWEAVER_BASE_URL;
|
|
77
|
+
baseUrl = opts.baseUrl ?? envUrl;
|
|
78
|
+
if (!baseUrl) {
|
|
79
|
+
const platform = getCurrentPlatform();
|
|
80
|
+
if (platform)
|
|
81
|
+
baseUrl = platform;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (!baseUrl) {
|
|
85
|
+
throw new Error("KWeaverClient: baseUrl is required when auth is false. " +
|
|
86
|
+
"Pass it explicitly, set KWEAVER_BASE_URL, or run `kweaver auth login`.");
|
|
87
|
+
}
|
|
88
|
+
this._baseUrl = baseUrl.replace(/\/+$/, "");
|
|
89
|
+
this._accessToken = NO_AUTH_TOKEN;
|
|
90
|
+
this._businessDomain = opts.businessDomain ?? envDomain ?? "bd_public";
|
|
91
|
+
this.knowledgeNetworks = new KnowledgeNetworksResource(this);
|
|
92
|
+
this.agents = new AgentsResource(this);
|
|
93
|
+
this.bkn = new BknResource(this);
|
|
94
|
+
this.conversations = new ConversationsResource(this);
|
|
95
|
+
this.dataflows = new DataflowsResource(this);
|
|
96
|
+
this.datasources = new DataSourcesResource(this);
|
|
97
|
+
this.dataviews = new DataViewsResource(this);
|
|
98
|
+
this.vega = new VegaResource(this);
|
|
99
|
+
this.skills = new SkillsResource(this);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
69
102
|
if (opts.config) {
|
|
70
103
|
// config: true — read exclusively from ~/.kweaver/, ignore env vars
|
|
71
104
|
const platform = getCurrentPlatform();
|
|
@@ -140,15 +173,22 @@ export class KWeaverClient {
|
|
|
140
173
|
accessToken: token.accessToken,
|
|
141
174
|
...opts,
|
|
142
175
|
});
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
176
|
+
if (!isNoAuth(token.accessToken)) {
|
|
177
|
+
// Quick probe — if the token was revoked server-side, force refresh
|
|
178
|
+
try {
|
|
179
|
+
const bd = client.base().businessDomain;
|
|
180
|
+
const probe = await fetch(`${token.baseUrl.replace(/\/+$/, "")}/api/ontology-manager/v1/knowledge-networks?limit=1`, { headers: buildHeaders(token.accessToken, bd) });
|
|
181
|
+
if (probe.status === 401) {
|
|
182
|
+
throw new Error("Access token revoked. Run `kweaver auth login` to re-authenticate.");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
if (e instanceof Error &&
|
|
187
|
+
e.message.startsWith("Access token revoked")) {
|
|
188
|
+
throw e;
|
|
189
|
+
}
|
|
190
|
+
// Network error — return client as-is, let the caller deal with it
|
|
148
191
|
}
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
// Network error — return client as-is, let the caller deal with it
|
|
152
192
|
}
|
|
153
193
|
return client;
|
|
154
194
|
}
|