@kweaver-ai/kweaver-sdk 0.5.1 → 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.
Files changed (95) hide show
  1. package/README.md +25 -2
  2. package/README.zh.md +24 -1
  3. package/dist/api/agent-chat.d.ts +8 -2
  4. package/dist/api/agent-chat.js +150 -44
  5. package/dist/api/agent-list.d.ts +35 -0
  6. package/dist/api/agent-list.js +95 -21
  7. package/dist/api/bkn-backend.d.ts +60 -0
  8. package/dist/api/bkn-backend.js +103 -10
  9. package/dist/api/business-domains.js +9 -5
  10. package/dist/api/context-loader.js +4 -1
  11. package/dist/api/conversations.d.ts +6 -3
  12. package/dist/api/conversations.js +29 -35
  13. package/dist/api/dataflow.js +1 -10
  14. package/dist/api/dataflow2.d.ts +95 -0
  15. package/dist/api/dataflow2.js +80 -0
  16. package/dist/api/datasources.js +1 -10
  17. package/dist/api/dataviews.js +1 -10
  18. package/dist/api/headers.d.ts +11 -0
  19. package/dist/api/headers.js +30 -0
  20. package/dist/api/knowledge-networks.d.ts +41 -0
  21. package/dist/api/knowledge-networks.js +69 -22
  22. package/dist/api/ontology-query.d.ts +14 -1
  23. package/dist/api/ontology-query.js +63 -49
  24. package/dist/api/semantic-search.js +2 -12
  25. package/dist/api/skills.d.ts +141 -0
  26. package/dist/api/skills.js +208 -0
  27. package/dist/api/vega.d.ts +54 -7
  28. package/dist/api/vega.js +112 -25
  29. package/dist/auth/oauth.d.ts +5 -1
  30. package/dist/auth/oauth.js +351 -95
  31. package/dist/cli.js +49 -5
  32. package/dist/client.d.ts +12 -0
  33. package/dist/client.js +52 -8
  34. package/dist/commands/agent.d.ts +33 -1
  35. package/dist/commands/agent.js +721 -49
  36. package/dist/commands/auth.js +226 -55
  37. package/dist/commands/bkn-ops.d.ts +77 -0
  38. package/dist/commands/bkn-ops.js +1056 -0
  39. package/dist/commands/bkn-query.d.ts +14 -0
  40. package/dist/commands/bkn-query.js +370 -0
  41. package/dist/commands/bkn-schema.d.ts +135 -0
  42. package/dist/commands/bkn-schema.js +1483 -0
  43. package/dist/commands/bkn-utils.d.ts +36 -0
  44. package/dist/commands/bkn-utils.js +102 -0
  45. package/dist/commands/bkn.d.ts +7 -113
  46. package/dist/commands/bkn.js +175 -2429
  47. package/dist/commands/call.js +8 -5
  48. package/dist/commands/dataflow.d.ts +1 -0
  49. package/dist/commands/dataflow.js +251 -0
  50. package/dist/commands/dataview.d.ts +7 -0
  51. package/dist/commands/dataview.js +38 -2
  52. package/dist/commands/ds.d.ts +1 -0
  53. package/dist/commands/ds.js +8 -1
  54. package/dist/commands/explore-bkn.d.ts +79 -0
  55. package/dist/commands/explore-bkn.js +273 -0
  56. package/dist/commands/explore-chat.d.ts +3 -0
  57. package/dist/commands/explore-chat.js +193 -0
  58. package/dist/commands/explore-vega.d.ts +3 -0
  59. package/dist/commands/explore-vega.js +71 -0
  60. package/dist/commands/explore.d.ts +9 -0
  61. package/dist/commands/explore.js +258 -0
  62. package/dist/commands/import-csv.d.ts +2 -0
  63. package/dist/commands/import-csv.js +3 -2
  64. package/dist/commands/skill.d.ts +26 -0
  65. package/dist/commands/skill.js +524 -0
  66. package/dist/commands/vega.js +372 -117
  67. package/dist/config/jwt.d.ts +6 -0
  68. package/dist/config/jwt.js +21 -0
  69. package/dist/config/no-auth.d.ts +3 -0
  70. package/dist/config/no-auth.js +5 -0
  71. package/dist/config/store.d.ts +45 -5
  72. package/dist/config/store.js +385 -30
  73. package/dist/index.d.ts +6 -1
  74. package/dist/index.js +5 -1
  75. package/dist/kweaver.d.ts +5 -0
  76. package/dist/kweaver.js +32 -2
  77. package/dist/resources/bkn.d.ts +4 -0
  78. package/dist/resources/bkn.js +6 -3
  79. package/dist/resources/conversations.d.ts +5 -2
  80. package/dist/resources/conversations.js +17 -3
  81. package/dist/resources/knowledge-networks.js +3 -8
  82. package/dist/resources/skills.d.ts +47 -0
  83. package/dist/resources/skills.js +47 -0
  84. package/dist/resources/vega.d.ts +11 -6
  85. package/dist/resources/vega.js +37 -10
  86. package/dist/templates/explorer/app.js +136 -0
  87. package/dist/templates/explorer/bkn.js +747 -0
  88. package/dist/templates/explorer/chat.js +980 -0
  89. package/dist/templates/explorer/dashboard.js +82 -0
  90. package/dist/templates/explorer/index.html +35 -0
  91. package/dist/templates/explorer/style.css +2440 -0
  92. package/dist/templates/explorer/vega.js +291 -0
  93. package/dist/utils/http.d.ts +3 -0
  94. package/dist/utils/http.js +37 -1
  95. package/package.json +9 -5
@@ -1,4 +1,5 @@
1
1
  import { ensureValidToken, formatHttpError, with401RefreshRetry } from "../auth/oauth.js";
2
+ import { isNoAuth } from "../config/no-auth.js";
2
3
  import { HttpError } from "../utils/http.js";
3
4
  import { resolveBusinessDomain } from "../config/store.js";
4
5
  export function parseCallArgs(args) {
@@ -74,11 +75,13 @@ export function parseCallArgs(args) {
74
75
  return { url, method, headers, body, pretty, verbose, businessDomain };
75
76
  }
76
77
  function injectAuthHeaders(headers, accessToken, businessDomain) {
77
- if (!headers.has("authorization")) {
78
- headers.set("authorization", `Bearer ${accessToken}`);
79
- }
80
- if (!headers.has("token")) {
81
- headers.set("token", accessToken);
78
+ if (!isNoAuth(accessToken)) {
79
+ if (!headers.has("authorization")) {
80
+ headers.set("authorization", `Bearer ${accessToken}`);
81
+ }
82
+ if (!headers.has("token")) {
83
+ headers.set("token", accessToken);
84
+ }
82
85
  }
83
86
  if (!headers.has("x-business-domain")) {
84
87
  headers.set("x-business-domain", businessDomain);
@@ -0,0 +1 @@
1
+ export declare function runDataflowCommand(args: string[]): Promise<number>;
@@ -0,0 +1,251 @@
1
+ import { access, readFile } from "node:fs/promises";
2
+ import { constants } from "node:fs";
3
+ import columnify from "columnify";
4
+ import stringWidth from "string-width";
5
+ import yargs from "yargs";
6
+ import { ensureValidToken, formatHttpError, with401RefreshRetry } from "../auth/oauth.js";
7
+ import { resolveBusinessDomain } from "../config/store.js";
8
+ import { getDataflowLogsPage, listDataflowRuns, listDataflows, runDataflowWithFile, runDataflowWithRemoteUrl, } from "../api/dataflow2.js";
9
+ function renderTable(rows) {
10
+ if (rows.length === 0)
11
+ return "";
12
+ return columnify(rows, {
13
+ showHeaders: true,
14
+ preserveNewLines: true,
15
+ stringLength: stringWidth,
16
+ headingTransform: (heading) => heading,
17
+ });
18
+ }
19
+ function buildListTableRows(items) {
20
+ return items.map((item) => ({
21
+ "ID": item.id,
22
+ "Title": item.title ?? "",
23
+ "Status": item.status ?? "",
24
+ "Trigger": item.trigger ?? "",
25
+ "Creator": item.creator ?? "",
26
+ "Updated At": item.updated_at != null ? String(item.updated_at) : "",
27
+ "Version ID": item.version_id ?? "",
28
+ }));
29
+ }
30
+ function buildRunTableRows(items) {
31
+ return items.map((item) => ({
32
+ "ID": item.id,
33
+ "Status": item.status ?? "",
34
+ "Started At": item.started_at != null ? String(item.started_at) : "",
35
+ "Ended At": item.ended_at != null ? String(item.ended_at) : "",
36
+ "Source Name": item.source?.name != null ? String(item.source.name) : "",
37
+ "Content Type": item.source?.content_type != null ? String(item.source.content_type) : "",
38
+ "Size": item.source?.size != null ? String(item.source.size) : "",
39
+ "Reason": item.reason ?? "",
40
+ }));
41
+ }
42
+ function parseSinceToLocalDayRange(value) {
43
+ // 只支持 YYYY-MM-DD 格式,解析为本地时区的一整天范围
44
+ const match = value.match(/^(\d{4})-(\d{2})-(\d{2})$/);
45
+ if (!match)
46
+ return null;
47
+ const year = parseInt(match[1], 10);
48
+ const month = parseInt(match[2], 10) - 1; // Date month is 0-indexed
49
+ const day = parseInt(match[3], 10);
50
+ const start = new Date(year, month, day, 0, 0, 0);
51
+ const end = new Date(year, month, day, 23, 59, 59);
52
+ return {
53
+ startTime: Math.floor(start.getTime() / 1000),
54
+ endTime: Math.floor(end.getTime() / 1000),
55
+ };
56
+ }
57
+ function formatDataflowLogSummary(item) {
58
+ const duration = item.metadata?.duration ?? "-";
59
+ return [
60
+ `[${item.id}] ${item.taskId ?? ""} ${item.operator ?? ""}`,
61
+ `Status: ${item.status ?? ""}`,
62
+ `Started At: ${item.started_at ?? ""}`,
63
+ `Updated At: ${item.updated_at ?? ""}`,
64
+ `Duration: ${duration}`
65
+ ].join("\n");
66
+ }
67
+ function formatIndentedJsonBlock(label, value) {
68
+ const pretty = JSON.stringify(value ?? {}, null, 4) ?? "{}";
69
+ const indented = pretty
70
+ .split("\n")
71
+ .map((line) => ` ${line}`)
72
+ .join("\n");
73
+ return ` ${label}:\n${indented}`;
74
+ }
75
+ function formatDataflowLogOutput(item, detail) {
76
+ const parts = [formatDataflowLogSummary(item)];
77
+ if (detail) {
78
+ parts.push("");
79
+ parts.push(formatIndentedJsonBlock("input", item.inputs ?? {}));
80
+ parts.push("");
81
+ parts.push(formatIndentedJsonBlock("output", item.outputs ?? {}));
82
+ }
83
+ return parts.join("\n");
84
+ }
85
+ async function requireTokenAndBusinessDomain(businessDomain) {
86
+ const token = await ensureValidToken();
87
+ return {
88
+ baseUrl: token.baseUrl,
89
+ accessToken: token.accessToken,
90
+ businessDomain: businessDomain || resolveBusinessDomain(),
91
+ };
92
+ }
93
+ export async function runDataflowCommand(args) {
94
+ let exitCode = 0;
95
+ const parser = yargs(args)
96
+ .scriptName("kweaver dataflow")
97
+ .exitProcess(false)
98
+ .help()
99
+ .version(false)
100
+ .strict()
101
+ .fail((message, error) => {
102
+ throw error ?? new Error(message);
103
+ })
104
+ .command("list", "List all dataflows", (command) => command.option("biz-domain", {
105
+ alias: "bd",
106
+ type: "string",
107
+ }), async (argv) => {
108
+ exitCode = await with401RefreshRetry(async () => {
109
+ const base = await requireTokenAndBusinessDomain(argv.bizDomain);
110
+ const body = await listDataflows(base);
111
+ const table = renderTable(buildListTableRows(body.dags));
112
+ if (table) {
113
+ console.log(table);
114
+ }
115
+ return 0;
116
+ });
117
+ })
118
+ .command("run <dagId>", "Trigger one dataflow run", (command) => command
119
+ .positional("dagId", { type: "string" })
120
+ .option("file", { type: "string" })
121
+ .option("url", { type: "string" })
122
+ .option("name", { type: "string" })
123
+ .option("biz-domain", { alias: "bd", type: "string" })
124
+ .check((argv) => {
125
+ const hasFile = typeof argv.file === "string";
126
+ const hasUrl = typeof argv.url === "string";
127
+ if (hasFile === hasUrl) {
128
+ throw new Error("Exactly one of --file or --url is required.");
129
+ }
130
+ if (hasUrl && typeof argv.name !== "string") {
131
+ throw new Error("--url requires --name.");
132
+ }
133
+ return true;
134
+ }), async (argv) => {
135
+ exitCode = await with401RefreshRetry(async () => {
136
+ const base = await requireTokenAndBusinessDomain(argv.bizDomain);
137
+ if (typeof argv.file === "string") {
138
+ await access(argv.file, constants.R_OK);
139
+ const fileBytes = await readFile(argv.file);
140
+ const fileName = argv.file.split(/[\\/]/).pop() || "upload.bin";
141
+ const body = await runDataflowWithFile({
142
+ ...base,
143
+ dagId: argv.dagId,
144
+ fileName,
145
+ fileBytes,
146
+ });
147
+ console.log(body.dag_instance_id);
148
+ return 0;
149
+ }
150
+ const body = await runDataflowWithRemoteUrl({
151
+ ...base,
152
+ dagId: argv.dagId,
153
+ url: String(argv.url),
154
+ name: String(argv.name),
155
+ });
156
+ console.log(body.dag_instance_id);
157
+ return 0;
158
+ });
159
+ })
160
+ .command("runs <dagId>", "List run records for one dataflow", (command) => command
161
+ .positional("dagId", { type: "string" })
162
+ .option("since", { type: "string" })
163
+ .option("biz-domain", { alias: "bd", type: "string" }), async (argv) => {
164
+ exitCode = await with401RefreshRetry(async () => {
165
+ const base = await requireTokenAndBusinessDomain(argv.bizDomain);
166
+ const dayRange = typeof argv.since === "string" ? parseSinceToLocalDayRange(argv.since) : null;
167
+ let results = [];
168
+ if (!dayRange) {
169
+ const body = await listDataflowRuns({
170
+ ...base,
171
+ dagId: argv.dagId,
172
+ page: 0,
173
+ limit: 20,
174
+ sortBy: "started_at",
175
+ order: "desc",
176
+ });
177
+ results = body.results;
178
+ }
179
+ else {
180
+ const first = await listDataflowRuns({
181
+ ...base,
182
+ dagId: argv.dagId,
183
+ page: 0,
184
+ limit: 20,
185
+ sortBy: "started_at",
186
+ order: "desc",
187
+ startTime: dayRange.startTime,
188
+ endTime: dayRange.endTime,
189
+ });
190
+ results = [...first.results];
191
+ const total = first.total ?? first.results.length;
192
+ for (let page = 1; page * 20 < total; page += 1) {
193
+ const next = await listDataflowRuns({
194
+ ...base,
195
+ dagId: argv.dagId,
196
+ page,
197
+ limit: 20,
198
+ sortBy: "started_at",
199
+ order: "desc",
200
+ startTime: dayRange.startTime,
201
+ endTime: dayRange.endTime,
202
+ });
203
+ results = results.concat(next.results);
204
+ }
205
+ }
206
+ const table = renderTable(buildRunTableRows(results));
207
+ if (table) {
208
+ console.log(table);
209
+ }
210
+ return 0;
211
+ });
212
+ })
213
+ .command("logs <dagId> <instanceId>", "Show logs for one run in summary or detail mode", (command) => command
214
+ .positional("dagId", { type: "string" })
215
+ .positional("instanceId", { type: "string" })
216
+ .option("detail", { type: "boolean", default: false })
217
+ .option("biz-domain", { alias: "bd", type: "string" }), async (argv) => {
218
+ exitCode = await with401RefreshRetry(async () => {
219
+ const base = await requireTokenAndBusinessDomain(argv.bizDomain);
220
+ let seen = 0;
221
+ for (let page = 0;; page += 1) {
222
+ const body = await getDataflowLogsPage({
223
+ ...base,
224
+ dagId: argv.dagId,
225
+ instanceId: argv.instanceId,
226
+ page,
227
+ limit: 100,
228
+ });
229
+ if (body.results.length === 0)
230
+ break;
231
+ for (const item of body.results) {
232
+ console.log(formatDataflowLogOutput(item, argv.detail === true));
233
+ console.log("");
234
+ }
235
+ seen += body.results.length;
236
+ if ((body.total ?? 0) > 0 && seen >= (body.total ?? 0))
237
+ break;
238
+ }
239
+ return 0;
240
+ });
241
+ })
242
+ .demandCommand(1);
243
+ try {
244
+ await parser.parseAsync();
245
+ return exitCode;
246
+ }
247
+ catch (error) {
248
+ console.error(formatHttpError(error));
249
+ return 1;
250
+ }
251
+ }
@@ -1 +1,8 @@
1
+ /**
2
+ * Strip SQL line/block comments and leading whitespace, then return the first identifier token (lowercase).
3
+ * Used to reject DDL/DML passed to dataview query (server applies LIMIT semantics).
4
+ */
5
+ export declare function getFirstSqlTokenAfterComments(sql: string): string;
6
+ /** True if ad-hoc SQL is safe for dataview query (SELECT / WITH only). */
7
+ export declare function isDataviewSelectLikeSql(sql: string): boolean;
1
8
  export declare function runDataviewCommand(args: string[]): Promise<number>;
@@ -3,6 +3,33 @@ import { ensureValidToken, formatHttpError, with401RefreshRetry } from "../auth/
3
3
  import { deleteDataView, findDataView, getDataView, listDataViews, queryDataView, } from "../api/dataviews.js";
4
4
  import { formatCallOutput } from "./call.js";
5
5
  import { resolveBusinessDomain } from "../config/store.js";
6
+ /**
7
+ * Strip SQL line/block comments and leading whitespace, then return the first identifier token (lowercase).
8
+ * Used to reject DDL/DML passed to dataview query (server applies LIMIT semantics).
9
+ */
10
+ export function getFirstSqlTokenAfterComments(sql) {
11
+ let s = sql.replace(/\/\*[\s\S]*?\*\//g, " ");
12
+ const lines = s.split("\n").map((line) => {
13
+ const idx = line.indexOf("--");
14
+ return idx >= 0 ? line.slice(0, idx) : line;
15
+ });
16
+ s = lines.join("\n");
17
+ s = s.replace(/\s+/g, " ").trim();
18
+ if (!s)
19
+ return "";
20
+ const match = /^([a-zA-Z_][a-zA-Z0-9_]*|"(?:[^"]|"")*")/.exec(s);
21
+ if (!match)
22
+ return "";
23
+ const tok = match[1];
24
+ if (tok.startsWith('"'))
25
+ return tok.slice(1, -1).replace(/""/g, '"').toLowerCase();
26
+ return tok.toLowerCase();
27
+ }
28
+ /** True if ad-hoc SQL is safe for dataview query (SELECT / WITH only). */
29
+ export function isDataviewSelectLikeSql(sql) {
30
+ const kw = getFirstSqlTokenAfterComments(sql);
31
+ return kw === "select" || kw === "with";
32
+ }
6
33
  function confirmYes(prompt) {
7
34
  return new Promise((resolve) => {
8
35
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -27,7 +54,7 @@ Subcommands:
27
54
 
28
55
  list — list all data views (no keyword search)
29
56
  find — search by name; default fuzzy, --exact for strict match, --wait to poll
30
- query — run SQL query against a data view (mdl-uniquery); omit --sql to use view default SQL`);
57
+ query — run SQL query against a data view (mdl-uniquery); omit --sql to use view default SQL; only SELECT/WITH unless --raw-sql`);
31
58
  return 0;
32
59
  }
33
60
  const dispatch = () => {
@@ -214,8 +241,9 @@ async function runDataviewQueryCommand(args) {
214
241
  let limit = 50;
215
242
  let offset = 0;
216
243
  let needTotal = false;
244
+ let rawSql = false;
217
245
  if (args.length === 0 || args[0].startsWith("-")) {
218
- console.error("Usage: kweaver dataview query <id> [--sql <sql>] [--limit <n>] [--offset <n>] [--need-total] [-bd value] [--pretty]");
246
+ console.error("Usage: kweaver dataview query <id> [--sql <sql>] [--limit <n>] [--offset <n>] [--need-total] [--raw-sql] [-bd value] [--pretty]");
219
247
  return 1;
220
248
  }
221
249
  const id = args[0];
@@ -228,6 +256,10 @@ async function runDataviewQueryCommand(args) {
228
256
  }
229
257
  if (arg === "--pretty")
230
258
  continue;
259
+ if (arg === "--raw-sql") {
260
+ rawSql = true;
261
+ continue;
262
+ }
231
263
  if ((arg === "--sql" || arg === "-s") && tail[i + 1]) {
232
264
  sql = tail[++i];
233
265
  continue;
@@ -249,6 +281,10 @@ async function runDataviewQueryCommand(args) {
249
281
  continue;
250
282
  }
251
283
  }
284
+ if (sql !== undefined && sql !== "" && !rawSql && !isDataviewSelectLikeSql(sql)) {
285
+ console.error("dataview query only supports SELECT statements (or WITH for CTEs). Use --raw-sql to send other SQL at your own risk.");
286
+ return 1;
287
+ }
252
288
  const token = await ensureValidToken();
253
289
  const result = await queryDataView({
254
290
  baseUrl: token.baseUrl,
@@ -11,6 +11,7 @@ export declare function parseImportCsvArgs(args: string[]): {
11
11
  tablePrefix: string;
12
12
  batchSize: number;
13
13
  businessDomain: string;
14
+ recreate: boolean;
14
15
  };
15
16
  export declare function resolveFiles(pattern: string): Promise<string[]>;
16
17
  export interface ImportCsvResult {
@@ -306,6 +306,7 @@ Options:
306
306
  --files <s> CSV file paths (comma-separated or glob pattern, required)
307
307
  --table-prefix <s> Table name prefix (default: none)
308
308
  --batch-size <n> Rows per batch (default: 500, range: 1-10000)
309
+ --recreate First batch uses overwrite (drop/recreate table) then append; use when schema changed
309
310
  -bd, --biz-domain Business domain (default: bd_public)`;
310
311
  export function parseImportCsvArgs(args) {
311
312
  let datasourceId = "";
@@ -313,6 +314,7 @@ export function parseImportCsvArgs(args) {
313
314
  let tablePrefix = "";
314
315
  let batchSize = 500;
315
316
  let businessDomain = "";
317
+ let recreate = false;
316
318
  for (let i = 0; i < args.length; i += 1) {
317
319
  const arg = args[i];
318
320
  if (arg === "--help" || arg === "-h")
@@ -321,6 +323,10 @@ export function parseImportCsvArgs(args) {
321
323
  files = args[++i];
322
324
  continue;
323
325
  }
326
+ if (arg === "--recreate") {
327
+ recreate = true;
328
+ continue;
329
+ }
324
330
  if (arg === "--table-prefix" && args[i + 1]) {
325
331
  tablePrefix = args[++i];
326
332
  continue;
@@ -343,7 +349,7 @@ export function parseImportCsvArgs(args) {
343
349
  }
344
350
  if (!businessDomain)
345
351
  businessDomain = resolveBusinessDomain();
346
- return { datasourceId, files, tablePrefix, batchSize, businessDomain };
352
+ return { datasourceId, files, tablePrefix, batchSize, businessDomain, recreate };
347
353
  }
348
354
  export async function resolveFiles(pattern) {
349
355
  const parts = pattern.split(",").map((p) => p.trim()).filter(Boolean);
@@ -446,6 +452,7 @@ export async function runDsImportCsv(args) {
446
452
  tableExist,
447
453
  data: batch,
448
454
  fieldMappings,
455
+ recreate: options.recreate,
449
456
  });
450
457
  const t0 = Date.now();
451
458
  process.stderr.write(`[${tableName}] batch ${batchLabel} (${rowCount} rows)... `);
@@ -0,0 +1,79 @@
1
+ import { IncomingMessage, ServerResponse } from "node:http";
2
+ export interface ExploreMeta {
3
+ bkn: {
4
+ id: string;
5
+ name: string;
6
+ };
7
+ statistics: {
8
+ object_count: number;
9
+ relation_count: number;
10
+ };
11
+ objectTypes: Array<{
12
+ id: string;
13
+ name: string;
14
+ displayKey: string;
15
+ propertyCount: number;
16
+ properties: Array<{
17
+ name: string;
18
+ type?: string;
19
+ }>;
20
+ }>;
21
+ relationTypes: Array<{
22
+ id: string;
23
+ name: string;
24
+ sourceOtId: string;
25
+ targetOtId: string;
26
+ sourceOtName: string;
27
+ targetOtName: string;
28
+ }>;
29
+ actionTypes: Array<{
30
+ id: string;
31
+ name: string;
32
+ }>;
33
+ }
34
+ export interface ExploreOt {
35
+ id: string;
36
+ name: string;
37
+ displayKey: string;
38
+ propertyCount: number;
39
+ properties: Array<{
40
+ name: string;
41
+ type?: string;
42
+ }>;
43
+ }
44
+ export interface ExploreRt {
45
+ id: string;
46
+ name: string;
47
+ sourceOtId: string;
48
+ targetOtId: string;
49
+ sourceOtName: string;
50
+ targetOtName: string;
51
+ }
52
+ export interface ExploreAt {
53
+ id: string;
54
+ name: string;
55
+ }
56
+ export interface ExploreBkn {
57
+ id: string;
58
+ name: string;
59
+ }
60
+ export interface ExploreStats {
61
+ object_count: number;
62
+ relation_count: number;
63
+ }
64
+ export declare const EXPLORE_BOOTSTRAP_RETRY_DELAY_MS = 300;
65
+ export declare const EXPLORE_BOOTSTRAP_MAX_ATTEMPTS = 2;
66
+ export declare function buildMeta(knRaw: string, otRaw: string, rtRaw: string, atRaw: string): ExploreMeta;
67
+ export declare function isRetryableExploreBootstrapError(error: unknown): boolean;
68
+ export declare function loadExploreMetaWithRetry(token: {
69
+ baseUrl: string;
70
+ accessToken: string;
71
+ }, knId: string, businessDomain: string): Promise<ExploreMeta>;
72
+ export declare function readBody(req: IncomingMessage): Promise<string>;
73
+ export declare function jsonResponse(res: ServerResponse, status: number, data: unknown): void;
74
+ export declare function handleApiError(res: ServerResponse, error: unknown): void;
75
+ export type TokenProvider = () => Promise<{
76
+ baseUrl: string;
77
+ accessToken: string;
78
+ }>;
79
+ export declare function registerBknRoutes(meta: ExploreMeta, getToken: TokenProvider, businessDomain: string): Map<string, (req: IncomingMessage, res: ServerResponse) => void>;