@kweaver-ai/kweaver-sdk 0.7.3 → 0.8.1

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 (88) hide show
  1. package/README.md +49 -0
  2. package/README.zh.md +44 -0
  3. package/bin/kweaver.js +12 -11
  4. package/dist/api/agent-observability.d.ts +51 -0
  5. package/dist/api/agent-observability.js +108 -0
  6. package/dist/api/bkn-backend.d.ts +1 -0
  7. package/dist/api/bkn-backend.js +1 -1
  8. package/dist/api/bkn-metrics.d.ts +59 -0
  9. package/dist/api/bkn-metrics.js +129 -0
  10. package/dist/api/conversations.d.ts +43 -2
  11. package/dist/api/conversations.js +77 -23
  12. package/dist/api/datasources.d.ts +2 -20
  13. package/dist/api/datasources.js +7 -86
  14. package/dist/api/model-invocation.d.ts +58 -0
  15. package/dist/api/model-invocation.js +203 -0
  16. package/dist/api/models.d.ts +79 -0
  17. package/dist/api/models.js +183 -0
  18. package/dist/api/ontology-query-metrics.d.ts +14 -0
  19. package/dist/api/ontology-query-metrics.js +30 -0
  20. package/dist/api/trace.d.ts +44 -0
  21. package/dist/api/trace.js +81 -0
  22. package/dist/api/vega.d.ts +53 -0
  23. package/dist/api/vega.js +144 -0
  24. package/dist/bundled-model-templates.d.ts +17 -0
  25. package/dist/bundled-model-templates.js +24 -0
  26. package/dist/cli.js +15 -0
  27. package/dist/client.d.ts +3 -0
  28. package/dist/client.js +5 -0
  29. package/dist/commands/agent.d.ts +7 -1
  30. package/dist/commands/agent.js +75 -21
  31. package/dist/commands/bkn-metric.d.ts +1 -0
  32. package/dist/commands/bkn-metric.js +406 -0
  33. package/dist/commands/bkn-ops.js +28 -16
  34. package/dist/commands/bkn-utils.d.ts +38 -0
  35. package/dist/commands/bkn-utils.js +54 -0
  36. package/dist/commands/bkn.js +4 -0
  37. package/dist/commands/ds.js +14 -3
  38. package/dist/commands/explore-chat.js +2 -2
  39. package/dist/commands/model.d.ts +72 -0
  40. package/dist/commands/model.js +1315 -0
  41. package/dist/commands/trace.d.ts +14 -0
  42. package/dist/commands/trace.js +168 -0
  43. package/dist/index.d.ts +9 -0
  44. package/dist/index.js +5 -0
  45. package/dist/resources/datasources.js +2 -1
  46. package/dist/resources/models.d.ts +40 -0
  47. package/dist/resources/models.js +88 -0
  48. package/dist/templates/model/llm-basic.json +13 -0
  49. package/dist/templates/model/manifest.json +16 -0
  50. package/dist/templates/model/small-basic.json +6 -0
  51. package/dist/trace-core/diagnose/builtin-rules/excessive-tool-calls-per-turn.d.ts +2 -0
  52. package/dist/trace-core/diagnose/builtin-rules/excessive-tool-calls-per-turn.js +15 -0
  53. package/dist/trace-core/diagnose/builtin-rules/excessive-tool-calls-per-turn.yaml +16 -0
  54. package/dist/trace-core/diagnose/builtin-rules/llm-response-truncated-no-continue.d.ts +2 -0
  55. package/dist/trace-core/diagnose/builtin-rules/llm-response-truncated-no-continue.js +44 -0
  56. package/dist/trace-core/diagnose/builtin-rules/llm-response-truncated-no-continue.yaml +15 -0
  57. package/dist/trace-core/diagnose/builtin-rules/register.d.ts +1 -0
  58. package/dist/trace-core/diagnose/builtin-rules/register.js +11 -0
  59. package/dist/trace-core/diagnose/builtin-rules/retrieval-empty-no-fallback.d.ts +2 -0
  60. package/dist/trace-core/diagnose/builtin-rules/retrieval-empty-no-fallback.js +29 -0
  61. package/dist/trace-core/diagnose/builtin-rules/retrieval-empty-no-fallback.yaml +15 -0
  62. package/dist/trace-core/diagnose/builtin-rules/tool-error-swallowed.d.ts +2 -0
  63. package/dist/trace-core/diagnose/builtin-rules/tool-error-swallowed.js +45 -0
  64. package/dist/trace-core/diagnose/builtin-rules/tool-error-swallowed.yaml +15 -0
  65. package/dist/trace-core/diagnose/builtin-rules/tool-loop-no-state-change.d.ts +2 -0
  66. package/dist/trace-core/diagnose/builtin-rules/tool-loop-no-state-change.js +38 -0
  67. package/dist/trace-core/diagnose/builtin-rules/tool-loop-no-state-change.yaml +16 -0
  68. package/dist/trace-core/diagnose/index.d.ts +9 -0
  69. package/dist/trace-core/diagnose/index.js +104 -0
  70. package/dist/trace-core/diagnose/predicate-registry.d.ts +7 -0
  71. package/dist/trace-core/diagnose/predicate-registry.js +30 -0
  72. package/dist/trace-core/diagnose/report-assembler.d.ts +12 -0
  73. package/dist/trace-core/diagnose/report-assembler.js +90 -0
  74. package/dist/trace-core/diagnose/rule-loader.d.ts +11 -0
  75. package/dist/trace-core/diagnose/rule-loader.js +86 -0
  76. package/dist/trace-core/diagnose/schemas.d.ts +109 -0
  77. package/dist/trace-core/diagnose/schemas.js +94 -0
  78. package/dist/trace-core/diagnose/signal-probe.d.ts +5 -0
  79. package/dist/trace-core/diagnose/signal-probe.js +21 -0
  80. package/dist/trace-core/diagnose/synthesizer-template.d.ts +2 -0
  81. package/dist/trace-core/diagnose/synthesizer-template.js +49 -0
  82. package/dist/trace-core/diagnose/trace-shaper.d.ts +3 -0
  83. package/dist/trace-core/diagnose/trace-shaper.js +72 -0
  84. package/dist/trace-core/diagnose/types.d.ts +124 -0
  85. package/dist/trace-core/diagnose/types.js +1 -0
  86. package/dist/utils/trace-views.d.ts +44 -0
  87. package/dist/utils/trace-views.js +425 -0
  88. package/package.json +15 -5
@@ -1,4 +1,5 @@
1
1
  import { buildHeaders } from "./headers.js";
2
+ import { fetchRawSpansByConversation } from "./agent-observability.js";
2
3
  function buildConversationsUrl(baseUrl, agentKey) {
3
4
  const base = baseUrl.replace(/\/+$/, "");
4
5
  return `${base}/api/agent-factory/v1/app/${agentKey}/conversation`;
@@ -29,33 +30,86 @@ export async function listConversations(opts) {
29
30
  }
30
31
  return body || "[]";
31
32
  }
32
- function buildTracesUrl(baseUrl, agentId, conversationId) {
33
- const base = baseUrl.replace(/\/+$/, "");
34
- return `${base}/api/agent-factory/v1/observability/agent/${agentId}/conversation/${conversationId}/session`;
33
+ function computeDurationNanos(source) {
34
+ if (typeof source.durationInNanos === "number")
35
+ return source.durationInNanos;
36
+ if (typeof source.duration === "number")
37
+ return source.duration;
38
+ const startTime = source.startTime ?? source.start_time;
39
+ const endTime = source.endTime ?? source.end_time;
40
+ if (typeof startTime !== "string" || typeof endTime !== "string")
41
+ return undefined;
42
+ const startMs = Date.parse(startTime);
43
+ const endMs = Date.parse(endTime);
44
+ if (Number.isNaN(startMs) || Number.isNaN(endMs))
45
+ return undefined;
46
+ return Math.max(0, (endMs - startMs) * 1e6);
47
+ }
48
+ function extractServiceName(source) {
49
+ if (typeof source.serviceName === "string")
50
+ return source.serviceName;
51
+ if (typeof source.service_name === "string")
52
+ return source.service_name;
53
+ const attributes = source.attributes;
54
+ if (typeof attributes?.["service.name"] === "string")
55
+ return attributes["service.name"];
56
+ const resource = source.resource;
57
+ if (typeof resource?.["service.name"] === "string")
58
+ return resource["service.name"];
59
+ const resourceService = resource?.service?.name;
60
+ if (typeof resourceService === "string")
61
+ return resourceService;
62
+ return undefined;
35
63
  }
64
+ function normalizeSpan(source) {
65
+ const traceId = String(source.traceId ?? source.trace_id ?? "");
66
+ const spanId = String(source.spanId ?? source.span_id ?? "");
67
+ if (!traceId || !spanId)
68
+ return null;
69
+ const parentRaw = source.parentSpanId ?? source.parent_span_id ?? source.parentSpanID;
70
+ const parentSpanId = parentRaw ? String(parentRaw) : undefined;
71
+ const status = source.status;
72
+ const attributes = source.attributes ?? undefined;
73
+ const events = source.events;
74
+ return {
75
+ traceId,
76
+ spanId,
77
+ parentSpanId: parentSpanId && parentSpanId !== "" && parentSpanId !== "0" ? parentSpanId : undefined,
78
+ name: String(source.name ?? ""),
79
+ kind: source.kind,
80
+ startTime: String(source.startTime ?? source.start_time ?? ""),
81
+ endTime: source.endTime ? String(source.endTime) : undefined,
82
+ durationInNanos: computeDurationNanos(source),
83
+ status,
84
+ serviceName: extractServiceName(source),
85
+ attributes,
86
+ events,
87
+ raw: source,
88
+ };
89
+ }
90
+ /**
91
+ * Fetch all spans belonging to a conversation, shaped as `TraceSpan[]` for UI
92
+ * rendering (tree/perf/evidence/reasoning views). The wire-level two-hop and
93
+ * auth/header concerns live in `./agent-observability`; this function only
94
+ * normalizes the raw `_source` documents.
95
+ */
36
96
  export async function getTracesByConversation(opts) {
37
- const { baseUrl, accessToken, agentId, conversationId, businessDomain = "bd_public" } = opts;
38
- const url = buildTracesUrl(baseUrl, agentId, conversationId);
39
- const response = await fetch(url, {
40
- method: "POST",
41
- headers: {
42
- "Content-Type": "application/json",
43
- accept: "application/json",
44
- ...buildHeaders(accessToken, businessDomain),
45
- },
46
- body: JSON.stringify({
47
- agent_id: agentId,
48
- start_time: 1,
49
- end_time: Date.now() + 86400000,
50
- page: 1,
51
- size: 50,
52
- }),
97
+ const { baseUrl, accessToken, conversationId, businessDomain = "bd_public", maxTraceIds, maxSpans, } = opts;
98
+ const fetched = await fetchRawSpansByConversation({
99
+ baseUrl,
100
+ accessToken,
101
+ businessDomain,
102
+ conversationId,
103
+ maxTraceIds,
104
+ maxSpans,
53
105
  });
54
- const body = await response.text();
55
- if (!response.ok) {
56
- throw new Error(`getTracesByConversation failed: HTTP ${response.status} ${response.statusText} — ${body.slice(0, 200)}`);
106
+ const spans = [];
107
+ for (const src of fetched.rawSources) {
108
+ const span = normalizeSpan(src);
109
+ if (span)
110
+ spans.push(span);
57
111
  }
58
- return body || "{}";
112
+ return { conversationId, traceIds: fetched.traceIds, spans, truncated: fetched.truncated };
59
113
  }
60
114
  /**
61
115
  * List messages for a conversation.
@@ -58,23 +58,5 @@ export interface ListTablesOptions {
58
58
  businessDomain?: string;
59
59
  }
60
60
  export declare function listTables(options: ListTablesOptions): Promise<string>;
61
- export interface ListTablesWithColumnsOptions extends ListTablesOptions {
62
- autoScan?: boolean;
63
- }
64
- /** List tables with column details. Optionally triggers metadata scan if no tables found. */
65
- export declare function listTablesWithColumns(options: ListTablesWithColumnsOptions): Promise<string>;
66
- export interface ScanMetadataOptions {
67
- baseUrl: string;
68
- accessToken: string;
69
- id: string;
70
- dsType?: string;
71
- businessDomain?: string;
72
- }
73
- export declare function scanMetadata(options: ScanMetadataOptions): Promise<string>;
74
- export interface ScanDatasourceMetadataOptions {
75
- baseUrl: string;
76
- accessToken: string;
77
- id: string;
78
- businessDomain?: string;
79
- }
80
- export declare function scanDatasourceMetadata(options: ScanDatasourceMetadataOptions): Promise<string>;
61
+ export { listTablesWithColumns, scanMetadata, scanDatasourceMetadata, } from "./vega.js";
62
+ export type { ListTablesWithColumnsOptions, ScanMetadataOptions, ScanDatasourceMetadataOptions, } from "./vega.js";
@@ -130,89 +130,10 @@ export async function listTables(options) {
130
130
  }
131
131
  return body;
132
132
  }
133
- /** List tables with column details. Optionally triggers metadata scan if no tables found. */
134
- export async function listTablesWithColumns(options) {
135
- const { id, autoScan = true, ...rest } = options;
136
- let body = await listTables({ ...rest, id });
137
- const parsed = JSON.parse(body);
138
- let items = Array.isArray(parsed) ? parsed : (parsed.entries ?? parsed.data ?? []);
139
- if (items.length === 0 && autoScan) {
140
- await scanMetadata({
141
- baseUrl: rest.baseUrl,
142
- accessToken: rest.accessToken,
143
- id,
144
- businessDomain: rest.businessDomain,
145
- });
146
- body = await listTables({ ...rest, id });
147
- const parsed2 = JSON.parse(body);
148
- items = Array.isArray(parsed2) ? parsed2 : (parsed2.entries ?? parsed2.data ?? []);
149
- }
150
- const base = rest.baseUrl.replace(/\/+$/, "");
151
- const tables = [];
152
- for (const t of items) {
153
- const tableId = String(t.id ?? "");
154
- const tableName = String(t.name ?? "");
155
- let columnsRaw = (t.columns ?? t.fields ?? []);
156
- if (columnsRaw.length === 0 && tableId) {
157
- const tableUrl = `${base}/api/data-connection/v1/metadata/table/${encodeURIComponent(tableId)}?limit=-1`;
158
- const colResponse = await fetch(tableUrl, {
159
- method: "GET",
160
- headers: buildHeaders(rest.accessToken, rest.businessDomain ?? "bd_public"),
161
- });
162
- const colData = (await colResponse.json());
163
- columnsRaw = Array.isArray(colData) ? colData : (colData.entries ?? colData.data ?? []);
164
- }
165
- const columns = columnsRaw.map((c) => ({
166
- name: String(c.name ?? c.field_name ?? ""),
167
- type: String(c.type ?? c.field_type ?? "varchar"),
168
- comment: typeof c.comment === "string" ? c.comment : undefined,
169
- }));
170
- tables.push({ name: tableName, columns });
171
- }
172
- return JSON.stringify(tables);
173
- }
174
- export async function scanMetadata(options) {
175
- const { baseUrl, accessToken, id, dsType = "mysql", businessDomain = "bd_public", } = options;
176
- const base = baseUrl.replace(/\/+$/, "");
177
- const scanUrl = `${base}/api/data-connection/v1/metadata/scan`;
178
- const statusUrl = (taskId) => `${base}/api/data-connection/v1/metadata/scan/${taskId}`;
179
- const scanBody = JSON.stringify({
180
- scan_name: `sdk_scan_${id.slice(0, 8)}`,
181
- type: 0,
182
- ds_info: { ds_id: id, ds_type: dsType },
183
- use_default_template: true,
184
- use_multi_threads: true,
185
- status: "open",
186
- });
187
- const scanResponse = await fetch(scanUrl, {
188
- method: "POST",
189
- headers: {
190
- ...buildHeaders(accessToken, businessDomain),
191
- "content-type": "application/json",
192
- },
193
- body: scanBody,
194
- });
195
- const scanResult = await scanResponse.json();
196
- const taskId = scanResult.id ?? "";
197
- for (let i = 0; i < 30; i += 1) {
198
- const delay = Math.min(2000 * Math.pow(1.5, i), 15000);
199
- await new Promise((r) => setTimeout(r, delay));
200
- const statusResponse = await fetch(statusUrl(taskId), {
201
- method: "GET",
202
- headers: buildHeaders(accessToken, businessDomain),
203
- });
204
- const statusData = (await statusResponse.json());
205
- if (statusData.status === "success" || statusData.status === "fail") {
206
- break;
207
- }
208
- }
209
- return taskId;
210
- }
211
- // Looks up a datasource's type then triggers a metadata scan, so callers
212
- // don't have to repeat the GET-then-scan dance whenever a flow needs the
213
- // platform catalog refreshed (after import-csv, before discovering tables).
214
- export async function scanDatasourceMetadata(options) {
215
- const dsBody = await getDatasource(options);
216
- const dsType = JSON.parse(dsBody).type ?? "mysql";
217
- return scanMetadata({ ...options, dsType });
218
- }
133
+ // ── Vega catalog re-exports (backward compatibility) ─────────────────────────
134
+ //
135
+ // listTablesWithColumns, scanMetadata, and scanDatasourceMetadata now live in
136
+ // vega.ts (they talk exclusively to vega-backend, not data-connection).
137
+ // Re-exported here so existing callers don't break — new code should import
138
+ // from "../api/vega.js" directly.
139
+ export { listTablesWithColumns, scanMetadata, scanDatasourceMetadata, } from "./vega.js";
@@ -0,0 +1,58 @@
1
+ export declare const MF_MODEL_API_PATH_PREFIX = "/api/mf-model-api/v1";
2
+ export interface MfApiBaseOptions {
3
+ baseUrl: string;
4
+ accessToken: string;
5
+ businessDomain?: string;
6
+ /**
7
+ * Replace platform origin for mf-model-api (still appends `/api/mf-model-api/v1`).
8
+ * Overrides `KWEAVER_MF_MODEL_API_URL` when set.
9
+ */
10
+ mfApiBaseUrl?: string;
11
+ }
12
+ export interface ChatMessage {
13
+ role: "system" | "user" | "assistant" | "tool";
14
+ content: string;
15
+ }
16
+ export interface ModelChatCompletionsOptions extends MfApiBaseOptions {
17
+ /** Platform LLM config id (snowflake); always sent as `model_id`. */
18
+ modelId: string;
19
+ /**
20
+ * Registry **`model_name`** for the OpenAI-style **`model`** field in the request body.
21
+ * When omitted, **`model`** defaults to **`modelId`** (historical CLI behaviour).
22
+ * Some gateways resolve routing via display name and reject numeric-only **`model`**.
23
+ */
24
+ modelName?: string;
25
+ messages: ChatMessage[];
26
+ stream?: boolean;
27
+ temperature?: number;
28
+ maxTokens?: number;
29
+ topP?: number;
30
+ topK?: number;
31
+ presencePenalty?: number;
32
+ frequencyPenalty?: number;
33
+ cache?: boolean;
34
+ verbose?: boolean;
35
+ }
36
+ export interface ModelChatResult {
37
+ text: string;
38
+ raw?: unknown;
39
+ }
40
+ /**
41
+ * Consume an OpenAI-style SSE stream (`data: {...}` / `data: [DONE]`).
42
+ */
43
+ export declare function consumeOpenAiSseText(response: Response, verbose?: boolean): Promise<string>;
44
+ export declare function modelChatCompletions(options: ModelChatCompletionsOptions): Promise<ModelChatResult>;
45
+ export interface ModelEmbeddingOptions extends MfApiBaseOptions {
46
+ modelId?: string;
47
+ modelName?: string;
48
+ input: string[];
49
+ }
50
+ export declare function modelEmbedding(options: ModelEmbeddingOptions): Promise<unknown>;
51
+ export declare function modelEmbeddings(options: ModelEmbeddingOptions): Promise<unknown>;
52
+ export interface ModelRerankOptions extends MfApiBaseOptions {
53
+ modelId?: string;
54
+ modelName?: string;
55
+ query: string;
56
+ documents: string[];
57
+ }
58
+ export declare function modelRerank(options: ModelRerankOptions): Promise<unknown>;
@@ -0,0 +1,203 @@
1
+ import { buildHeaders } from "./headers.js";
2
+ import { HttpError } from "../utils/http.js";
3
+ export const MF_MODEL_API_PATH_PREFIX = "/api/mf-model-api/v1";
4
+ function resolveApiOrigin(options) {
5
+ const env = process.env.KWEAVER_MF_MODEL_API_URL;
6
+ const raw = options.mfApiBaseUrl ?? (env && env.length > 0 ? env : undefined) ?? options.baseUrl;
7
+ return raw.replace(/\/+$/, "");
8
+ }
9
+ function apiEndpoint(options, relPath) {
10
+ const origin = resolveApiOrigin(options);
11
+ const path = relPath.startsWith("/") ? relPath : `/${relPath}`;
12
+ return `${origin}${MF_MODEL_API_PATH_PREFIX}${path}`;
13
+ }
14
+ function buildChatBody(options) {
15
+ const { modelId, modelName, messages, stream = false, temperature, maxTokens, topP, topK, presencePenalty, frequencyPenalty, cache, } = options;
16
+ const trimmedName = typeof modelName === "string" ? modelName.trim() : "";
17
+ const modelField = trimmedName.length > 0 ? trimmedName : modelId;
18
+ const body = {
19
+ model: modelField,
20
+ model_id: modelId,
21
+ messages,
22
+ stream,
23
+ };
24
+ if (temperature !== undefined)
25
+ body.temperature = temperature;
26
+ if (maxTokens !== undefined)
27
+ body.max_tokens = maxTokens;
28
+ if (topP !== undefined)
29
+ body.top_p = topP;
30
+ if (topK !== undefined)
31
+ body.top_k = topK;
32
+ if (presencePenalty !== undefined)
33
+ body.presence_penalty = presencePenalty;
34
+ if (frequencyPenalty !== undefined)
35
+ body.frequency_penalty = frequencyPenalty;
36
+ if (cache !== undefined)
37
+ body.cache = cache;
38
+ return body;
39
+ }
40
+ function extractOpenAiCompletionText(json) {
41
+ const choices = json.choices;
42
+ const msg = choices?.[0]?.message;
43
+ const content = msg?.content;
44
+ if (typeof content === "string")
45
+ return content;
46
+ return "";
47
+ }
48
+ function extractOpenAiDeltaChunk(chunk) {
49
+ const choices = chunk.choices;
50
+ if (!choices?.[0])
51
+ return "";
52
+ const delta = choices[0].delta;
53
+ const c = delta?.content;
54
+ if (typeof c === "string")
55
+ return c;
56
+ return "";
57
+ }
58
+ /**
59
+ * Consume an OpenAI-style SSE stream (`data: {...}` / `data: [DONE]`).
60
+ */
61
+ export async function consumeOpenAiSseText(response, verbose) {
62
+ const reader = response.body?.getReader();
63
+ if (!reader)
64
+ throw new Error("No response body for stream");
65
+ const decoder = new TextDecoder();
66
+ let buffer = "";
67
+ let out = "";
68
+ const processLine = (line) => {
69
+ const trimmed = line.trimEnd();
70
+ if (!trimmed.startsWith("data:"))
71
+ return;
72
+ const payload = trimmed.slice(5).trim();
73
+ if (payload === "[DONE]")
74
+ return;
75
+ try {
76
+ const chunk = JSON.parse(payload);
77
+ out += extractOpenAiDeltaChunk(chunk);
78
+ }
79
+ catch (e) {
80
+ if (verbose) {
81
+ const msg = e instanceof Error ? e.message : String(e);
82
+ console.error(`SSE parse skip: ${msg} payload=${payload.slice(0, 120)}`);
83
+ }
84
+ }
85
+ };
86
+ while (true) {
87
+ const { done, value } = await reader.read();
88
+ if (done)
89
+ break;
90
+ buffer += decoder.decode(value, { stream: true });
91
+ const lines = buffer.split("\n");
92
+ buffer = lines.pop() ?? "";
93
+ for (const ln of lines) {
94
+ processLine(ln);
95
+ }
96
+ }
97
+ if (buffer.trim())
98
+ processLine(buffer);
99
+ return out;
100
+ }
101
+ export async function modelChatCompletions(options) {
102
+ const { accessToken, businessDomain = "bd_public", stream = false, verbose } = options;
103
+ const url = apiEndpoint(options, "/chat/completions");
104
+ const body = buildChatBody({ ...options, stream });
105
+ const response = await fetch(url, {
106
+ method: "POST",
107
+ headers: {
108
+ ...buildHeaders(accessToken, businessDomain),
109
+ "content-type": "application/json",
110
+ accept: stream ? "text/event-stream" : "application/json",
111
+ },
112
+ body: JSON.stringify(body),
113
+ });
114
+ const contentType = response.headers.get("content-type") ?? "";
115
+ if (!response.ok) {
116
+ const text = await response.text();
117
+ throw new HttpError(response.status, response.statusText, text);
118
+ }
119
+ if (stream && contentType.includes("text/event-stream")) {
120
+ const text = await consumeOpenAiSseText(response, verbose);
121
+ return { text };
122
+ }
123
+ const text = await response.text();
124
+ const json = JSON.parse(text);
125
+ return { text: extractOpenAiCompletionText(json), raw: json };
126
+ }
127
+ // ── Small model invocation (mf-model-api) ───────────────────────────────────
128
+ /** OpenAI-style **`model`** for small-model routes: registry name when set, else **`model_id`** (matches chat completions). */
129
+ function resolveSmallInvokeModelField(modelName, modelId) {
130
+ const trimmedName = typeof modelName === "string" ? modelName.trim() : "";
131
+ if (trimmedName.length > 0)
132
+ return trimmedName;
133
+ const id = typeof modelId === "string" ? modelId.trim() : "";
134
+ if (id.length > 0)
135
+ return id;
136
+ return undefined;
137
+ }
138
+ export async function modelEmbedding(options) {
139
+ const { accessToken, businessDomain = "bd_public", modelId, modelName, input } = options;
140
+ const url = apiEndpoint(options, "/small-model/embedding");
141
+ const body = { input };
142
+ if (modelId)
143
+ body.model_id = modelId;
144
+ const modelField = resolveSmallInvokeModelField(modelName, modelId);
145
+ if (modelField !== undefined)
146
+ body.model = modelField;
147
+ const response = await fetch(url, {
148
+ method: "POST",
149
+ headers: {
150
+ ...buildHeaders(accessToken, businessDomain),
151
+ "content-type": "application/json",
152
+ },
153
+ body: JSON.stringify(body),
154
+ });
155
+ const text = await response.text();
156
+ if (!response.ok)
157
+ throw new HttpError(response.status, response.statusText, text);
158
+ return text ? JSON.parse(text) : null;
159
+ }
160
+ export async function modelEmbeddings(options) {
161
+ const { accessToken, businessDomain = "bd_public", modelId, modelName, input } = options;
162
+ const url = apiEndpoint(options, "/small-model/embeddings");
163
+ const body = { input };
164
+ if (modelId)
165
+ body.model_id = modelId;
166
+ const modelField = resolveSmallInvokeModelField(modelName, modelId);
167
+ if (modelField !== undefined)
168
+ body.model = modelField;
169
+ const response = await fetch(url, {
170
+ method: "POST",
171
+ headers: {
172
+ ...buildHeaders(accessToken, businessDomain),
173
+ "content-type": "application/json",
174
+ },
175
+ body: JSON.stringify(body),
176
+ });
177
+ const text = await response.text();
178
+ if (!response.ok)
179
+ throw new HttpError(response.status, response.statusText, text);
180
+ return text ? JSON.parse(text) : null;
181
+ }
182
+ export async function modelRerank(options) {
183
+ const { accessToken, businessDomain = "bd_public", modelId, modelName, query, documents } = options;
184
+ const url = apiEndpoint(options, "/small-model/reranker");
185
+ const body = { query, documents };
186
+ if (modelId)
187
+ body.model_id = modelId;
188
+ const modelField = resolveSmallInvokeModelField(modelName, modelId);
189
+ if (modelField !== undefined)
190
+ body.model = modelField;
191
+ const response = await fetch(url, {
192
+ method: "POST",
193
+ headers: {
194
+ ...buildHeaders(accessToken, businessDomain),
195
+ "content-type": "application/json",
196
+ },
197
+ body: JSON.stringify(body),
198
+ });
199
+ const text = await response.text();
200
+ if (!response.ok)
201
+ throw new HttpError(response.status, response.statusText, text);
202
+ return text ? JSON.parse(text) : null;
203
+ }
@@ -0,0 +1,79 @@
1
+ export declare const MF_MODEL_MANAGER_PATH_PREFIX = "/api/mf-model-manager/v1";
2
+ export interface MfManagerBaseOptions {
3
+ baseUrl: string;
4
+ accessToken: string;
5
+ businessDomain?: string;
6
+ /**
7
+ * Replace platform origin for mf-model-manager (still appends `/api/mf-model-manager/v1`).
8
+ * Overrides `KWEAVER_MF_MODEL_MANAGER_URL` when set.
9
+ */
10
+ mfManagerBaseUrl?: string;
11
+ }
12
+ /**
13
+ * Ensure small-model request bodies do not combine direct `model_config` with adapter mode.
14
+ */
15
+ export declare function assertSmallModelConfigAdapterExclusive(body: Record<string, unknown>): void;
16
+ /** For edit: validate mutual exclusion only when config or adapter fields are present. */
17
+ export declare function assertSmallModelEditBody(body: Record<string, unknown>): void;
18
+ export interface ListLlmModelsOptions extends MfManagerBaseOptions {
19
+ page: number;
20
+ size: number;
21
+ order?: string;
22
+ rule?: string;
23
+ series?: string;
24
+ name?: string;
25
+ apiModel?: string;
26
+ modelType?: string;
27
+ quota?: boolean;
28
+ }
29
+ export declare function listLlmModels(options: ListLlmModelsOptions): Promise<unknown>;
30
+ export interface GetLlmModelOptions extends MfManagerBaseOptions {
31
+ modelId: string;
32
+ }
33
+ export declare function getLlmModel(options: GetLlmModelOptions): Promise<unknown>;
34
+ export interface AddLlmModelOptions extends MfManagerBaseOptions {
35
+ body: Record<string, unknown>;
36
+ }
37
+ export declare function addLlmModel(options: AddLlmModelOptions): Promise<unknown>;
38
+ export interface EditLlmModelOptions extends MfManagerBaseOptions {
39
+ body: Record<string, unknown>;
40
+ }
41
+ export declare function editLlmModel(options: EditLlmModelOptions): Promise<unknown>;
42
+ export interface DeleteLlmModelsOptions extends MfManagerBaseOptions {
43
+ modelIds: string[];
44
+ }
45
+ export declare function deleteLlmModels(options: DeleteLlmModelsOptions): Promise<unknown>;
46
+ export interface TestLlmModelOptions extends MfManagerBaseOptions {
47
+ body: Record<string, unknown>;
48
+ }
49
+ export declare function testLlmModel(options: TestLlmModelOptions): Promise<unknown>;
50
+ export interface ListSmallModelsOptions extends MfManagerBaseOptions {
51
+ page: number;
52
+ size: number;
53
+ order?: string;
54
+ rule?: string;
55
+ modelName?: string;
56
+ modelType?: string;
57
+ modelSeries?: string;
58
+ }
59
+ export declare function listSmallModels(options: ListSmallModelsOptions): Promise<unknown>;
60
+ export interface GetSmallModelOptions extends MfManagerBaseOptions {
61
+ modelId: string;
62
+ }
63
+ export declare function getSmallModel(options: GetSmallModelOptions): Promise<unknown>;
64
+ export interface AddSmallModelOptions extends MfManagerBaseOptions {
65
+ body: Record<string, unknown>;
66
+ }
67
+ export declare function addSmallModel(options: AddSmallModelOptions): Promise<unknown>;
68
+ export interface EditSmallModelOptions extends MfManagerBaseOptions {
69
+ body: Record<string, unknown>;
70
+ }
71
+ export declare function editSmallModel(options: EditSmallModelOptions): Promise<unknown>;
72
+ export interface DeleteSmallModelsOptions extends MfManagerBaseOptions {
73
+ modelIds: string[];
74
+ }
75
+ export declare function deleteSmallModels(options: DeleteSmallModelsOptions): Promise<unknown>;
76
+ export interface TestSmallModelOptions extends MfManagerBaseOptions {
77
+ body: Record<string, unknown>;
78
+ }
79
+ export declare function testSmallModel(options: TestSmallModelOptions): Promise<unknown>;