@babav/knowledge-core-client 0.17.0 → 0.20.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 +4 -2
- package/dist/index.d.ts +68 -18
- package/dist/index.js +26 -39
- package/dist/visual/index.d.ts +9 -0
- package/dist/visual/index.js +9 -0
- package/dist/visual/types.d.ts +105 -0
- package/dist/visual/types.js +14 -0
- package/package.json +15 -5
- package/src/index.ts +81 -43
- package/src/visual/index.ts +10 -0
- package/src/visual/types.ts +132 -0
package/README.md
CHANGED
|
@@ -31,9 +31,11 @@ import { KnowledgeCoreClient } from "npm:@babav/knowledge-core-client";
|
|
|
31
31
|
## Usage
|
|
32
32
|
|
|
33
33
|
```ts
|
|
34
|
+
// You supply baseUrl + your tenant key at construction (from wherever your app keeps
|
|
35
|
+
// its config/secrets). The SDK never reads the environment or defaults a key itself.
|
|
34
36
|
const kc = new KnowledgeCoreClient({
|
|
35
|
-
baseUrl: "https://babav
|
|
36
|
-
apiKey:
|
|
37
|
+
baseUrl: "https://knowledgecore.babav.ai",
|
|
38
|
+
apiKey: myTenantKey, // your tenant key, provided by your app
|
|
37
39
|
});
|
|
38
40
|
|
|
39
41
|
// One-shot grounded query
|
package/dist/index.d.ts
CHANGED
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
* key for all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
13
13
|
* agent management. The key is server-side only — never ship it to a browser.
|
|
14
14
|
*
|
|
15
|
-
* Configuration —
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `--allow-env` (without it, pass the values explicitly).
|
|
15
|
+
* Configuration — the CALLER supplies credentials at construction; the SDK never reads
|
|
16
|
+
* the environment or defaults/derives a key itself:
|
|
17
|
+
* new KnowledgeCoreClient({ baseUrl, apiKey }) // apiKey = a TENANT key
|
|
18
|
+
* new AdminClient({ baseUrl, apiKey }) // apiKey = the ADMIN key
|
|
19
|
+
* The app decides where its key comes from (its own env/secret store) and passes it in.
|
|
20
|
+
* A missing baseUrl or apiKey throws at construction with a clear message.
|
|
22
21
|
*/
|
|
23
22
|
export type UUID = string;
|
|
23
|
+
export type { VisualEnvelope, VisualPayload, VisualElement, VisualComposition, VisualRegister, ChartBlockElement, } from "./visual/types.js";
|
|
24
24
|
export interface Page<T> {
|
|
25
25
|
items: T[];
|
|
26
26
|
next_cursor: string | null;
|
|
@@ -65,12 +65,52 @@ export interface QueryOverrides {
|
|
|
65
65
|
grounding_enabled?: boolean;
|
|
66
66
|
citations_enabled?: boolean;
|
|
67
67
|
}
|
|
68
|
+
/** Per-request visual overrides (see VisualRequest). */
|
|
69
|
+
export interface VisualOverrides {
|
|
70
|
+
concept_rounds_max?: number;
|
|
71
|
+
proposals_n?: number;
|
|
72
|
+
max_revisions?: number;
|
|
73
|
+
claims_check_model?: string;
|
|
74
|
+
vision_judge_model?: string;
|
|
75
|
+
scenic_enabled?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/** Per-request visual control. Absent => mode resolves from the agent default. All visual
|
|
78
|
+
* PROCESSING is server-side; the client only displays the result. */
|
|
79
|
+
export interface VisualRequest {
|
|
80
|
+
mode?: "off" | "on";
|
|
81
|
+
delivery?: "svg" | "json" | "both";
|
|
82
|
+
overrides?: VisualOverrides;
|
|
83
|
+
}
|
|
68
84
|
export interface QueryRequest {
|
|
69
85
|
corpus_ids: UUID[];
|
|
70
86
|
query: string;
|
|
71
87
|
conversation_id?: UUID | null;
|
|
72
88
|
overrides?: QueryOverrides;
|
|
73
89
|
filter?: MetadataFilter;
|
|
90
|
+
visual?: VisualRequest;
|
|
91
|
+
}
|
|
92
|
+
/** A visual attached to a response, anchored by char offsets into `answer` (SAME coordinate
|
|
93
|
+
* system as citations). For delivery="svg", `rendered_svg` is set; scenic sets `image`. */
|
|
94
|
+
export interface Visual {
|
|
95
|
+
id: string;
|
|
96
|
+
anchor: {
|
|
97
|
+
start: number;
|
|
98
|
+
end: number;
|
|
99
|
+
};
|
|
100
|
+
register: "chart" | "structural" | "conceptual" | "scenic";
|
|
101
|
+
priority: number;
|
|
102
|
+
payload: Record<string, unknown>;
|
|
103
|
+
rendered_svg?: string;
|
|
104
|
+
image?: {
|
|
105
|
+
url: string;
|
|
106
|
+
expires_at: number;
|
|
107
|
+
width: number;
|
|
108
|
+
height: number;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export interface VisualsMeta {
|
|
112
|
+
count: number;
|
|
113
|
+
dropped: number;
|
|
74
114
|
}
|
|
75
115
|
export interface QueryResponse {
|
|
76
116
|
conversation_id: UUID | null;
|
|
@@ -81,6 +121,8 @@ export interface QueryResponse {
|
|
|
81
121
|
groundedness: Groundedness | null;
|
|
82
122
|
usage: Record<string, number | null>;
|
|
83
123
|
standalone_query: string | null;
|
|
124
|
+
visuals?: Visual[];
|
|
125
|
+
visuals_meta?: VisualsMeta | null;
|
|
84
126
|
}
|
|
85
127
|
export interface Citation {
|
|
86
128
|
/** Char span IN THE ANSWER this citation supports (for highlighting). */
|
|
@@ -183,6 +225,10 @@ export interface Message {
|
|
|
183
225
|
groundedness: Record<string, unknown> | null;
|
|
184
226
|
retrieval_contents: unknown[] | null;
|
|
185
227
|
usage: Record<string, unknown> | null;
|
|
228
|
+
visuals?: {
|
|
229
|
+
items: Visual[];
|
|
230
|
+
meta: VisualsMeta;
|
|
231
|
+
} | null;
|
|
186
232
|
}
|
|
187
233
|
export interface Attachment {
|
|
188
234
|
id: UUID;
|
|
@@ -251,11 +297,11 @@ export declare class KnowledgeCoreError extends Error {
|
|
|
251
297
|
get code(): string | undefined;
|
|
252
298
|
}
|
|
253
299
|
export interface ClientOptions {
|
|
254
|
-
/** API base URL
|
|
255
|
-
baseUrl
|
|
256
|
-
/**
|
|
257
|
-
*
|
|
258
|
-
apiKey
|
|
300
|
+
/** API base URL — REQUIRED, supplied by the caller. */
|
|
301
|
+
baseUrl: string;
|
|
302
|
+
/** API key — REQUIRED, supplied by the caller (a TENANT key for KnowledgeCoreClient,
|
|
303
|
+
* the ADMIN key for AdminClient). The SDK never reads it from the environment. */
|
|
304
|
+
apiKey: string;
|
|
259
305
|
/** Optional default fetch timeout (ms). Streaming ignores this. */
|
|
260
306
|
timeoutMs?: number;
|
|
261
307
|
fetch?: typeof fetch;
|
|
@@ -272,7 +318,7 @@ declare class HttpBase {
|
|
|
272
318
|
protected readonly apiKey: string;
|
|
273
319
|
protected readonly timeoutMs?: number;
|
|
274
320
|
protected readonly _fetch: typeof fetch;
|
|
275
|
-
constructor(opts
|
|
321
|
+
constructor(opts: ClientOptions);
|
|
276
322
|
protected url(path: string, query?: RequestOpts["query"]): string;
|
|
277
323
|
protected raw(method: string, path: string, opts?: RequestOpts): Promise<Response>;
|
|
278
324
|
protected request<T>(method: string, path: string, opts?: RequestOpts): Promise<T>;
|
|
@@ -291,14 +337,19 @@ export interface StreamHandlers {
|
|
|
291
337
|
* (native path). Also present in `final`. May be `{}` if scoring was unavailable. */
|
|
292
338
|
onGroundedness?: (g: Groundedness | Record<string, never>) => void;
|
|
293
339
|
onFinal?: (d: QueryResponse) => void;
|
|
340
|
+
/** A visual, emitted (out of anchor order) during the trailing visual phase when
|
|
341
|
+
* visual.mode="on". Place by `anchor`, not arrival order. */
|
|
342
|
+
onVisual?: (v: Visual) => void;
|
|
343
|
+
/** Always emitted exactly once to close the visual phase (incl. count=0), before `done`. */
|
|
344
|
+
onVisualsComplete?: (m: VisualsMeta) => void;
|
|
294
345
|
onError?: (d: unknown) => void;
|
|
295
346
|
onDone?: () => void;
|
|
296
347
|
/** Catch-all for any event (incl. unknown ones). */
|
|
297
348
|
onEvent?: (event: string, data: unknown) => void;
|
|
298
349
|
}
|
|
299
350
|
export declare class KnowledgeCoreClient extends HttpBase {
|
|
300
|
-
/**
|
|
301
|
-
constructor(opts
|
|
351
|
+
/** @param opts.apiKey a TENANT key, supplied by the caller. */
|
|
352
|
+
constructor(opts: ClientOptions);
|
|
302
353
|
query(agentId: UUID, body: QueryRequest): Promise<QueryResponse>;
|
|
303
354
|
/** Streaming query (SSE). Resolves when the stream ends. */
|
|
304
355
|
queryStream(agentId: UUID, body: QueryRequest, handlers: StreamHandlers, signal?: AbortSignal): Promise<void>;
|
|
@@ -484,8 +535,8 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
484
535
|
};
|
|
485
536
|
}
|
|
486
537
|
export declare class AdminClient extends HttpBase {
|
|
487
|
-
/**
|
|
488
|
-
constructor(opts
|
|
538
|
+
/** @param opts.apiKey the ADMIN key, supplied by the caller. */
|
|
539
|
+
constructor(opts: ClientOptions);
|
|
489
540
|
tenants: {
|
|
490
541
|
create: (b: Partial<Tenant> & {
|
|
491
542
|
name: string;
|
|
@@ -529,4 +580,3 @@ export declare class AdminClient extends HttpBase {
|
|
|
529
580
|
delete: (id: UUID) => Promise<void>;
|
|
530
581
|
};
|
|
531
582
|
}
|
|
532
|
-
export {};
|
package/dist/index.js
CHANGED
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
* key for all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
13
13
|
* agent management. The key is server-side only — never ship it to a browser.
|
|
14
14
|
*
|
|
15
|
-
* Configuration —
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `--allow-env` (without it, pass the values explicitly).
|
|
15
|
+
* Configuration — the CALLER supplies credentials at construction; the SDK never reads
|
|
16
|
+
* the environment or defaults/derives a key itself:
|
|
17
|
+
* new KnowledgeCoreClient({ baseUrl, apiKey }) // apiKey = a TENANT key
|
|
18
|
+
* new AdminClient({ baseUrl, apiKey }) // apiKey = the ADMIN key
|
|
19
|
+
* The app decides where its key comes from (its own env/secret store) and passes it in.
|
|
20
|
+
* A missing baseUrl or apiKey throws at construction with a clear message.
|
|
22
21
|
*/
|
|
23
22
|
// ---------------------------------------------------------------------------
|
|
24
23
|
// Errors
|
|
@@ -43,37 +42,19 @@ export class KnowledgeCoreError extends Error {
|
|
|
43
42
|
return d?.detail?.error ?? d?.error;
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
|
-
/** Read an env var under Node (process.env) or Deno (Deno.env); undefined if unset
|
|
47
|
-
* or inaccessible (e.g. Deno without --allow-env). */
|
|
48
|
-
function readEnv(name) {
|
|
49
|
-
const g = globalThis;
|
|
50
|
-
const fromNode = g.process?.env?.[name];
|
|
51
|
-
if (fromNode)
|
|
52
|
-
return fromNode;
|
|
53
|
-
try {
|
|
54
|
-
const fromDeno = g.Deno?.env?.get?.(name);
|
|
55
|
-
if (fromDeno)
|
|
56
|
-
return fromDeno;
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
/* Deno env access denied (no --allow-env) — treat as unset */
|
|
60
|
-
}
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
45
|
class HttpBase {
|
|
64
46
|
baseUrl;
|
|
65
47
|
apiKey;
|
|
66
48
|
timeoutMs;
|
|
67
49
|
_fetch;
|
|
68
|
-
constructor(opts
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
this.
|
|
76
|
-
this.apiKey = apiKey;
|
|
50
|
+
constructor(opts) {
|
|
51
|
+
// Credentials come from the CALLER at init — the SDK never sources a key itself.
|
|
52
|
+
if (!opts?.baseUrl)
|
|
53
|
+
throw new Error("KnowledgeCore: { baseUrl } is required");
|
|
54
|
+
if (!opts?.apiKey)
|
|
55
|
+
throw new Error("KnowledgeCore: { apiKey } is required — the caller must supply the key at init");
|
|
56
|
+
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
57
|
+
this.apiKey = opts.apiKey;
|
|
77
58
|
this.timeoutMs = opts.timeoutMs;
|
|
78
59
|
this._fetch = opts.fetch ?? fetch;
|
|
79
60
|
}
|
|
@@ -162,9 +143,9 @@ const MULTIPART_MAX_BYTES = 30 * 1024 * 1024;
|
|
|
162
143
|
// Tenant client (data ops) — use a TENANT key
|
|
163
144
|
// ---------------------------------------------------------------------------
|
|
164
145
|
export class KnowledgeCoreClient extends HttpBase {
|
|
165
|
-
/**
|
|
166
|
-
constructor(opts
|
|
167
|
-
super(opts
|
|
146
|
+
/** @param opts.apiKey a TENANT key, supplied by the caller. */
|
|
147
|
+
constructor(opts) {
|
|
148
|
+
super(opts);
|
|
168
149
|
}
|
|
169
150
|
// --- query (agent-anchored) ---
|
|
170
151
|
query(agentId, body) {
|
|
@@ -329,9 +310,9 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
329
310
|
// Admin client (tenant + key + agent management) — use the ADMIN key
|
|
330
311
|
// ---------------------------------------------------------------------------
|
|
331
312
|
export class AdminClient extends HttpBase {
|
|
332
|
-
/**
|
|
333
|
-
constructor(opts
|
|
334
|
-
super(opts
|
|
313
|
+
/** @param opts.apiKey the ADMIN key, supplied by the caller. */
|
|
314
|
+
constructor(opts) {
|
|
315
|
+
super(opts);
|
|
335
316
|
}
|
|
336
317
|
tenants = {
|
|
337
318
|
create: (b) => this.request("POST", "/v1/tenants", { json: b }),
|
|
@@ -383,6 +364,12 @@ function dispatchSse(frame, h) {
|
|
|
383
364
|
case "final":
|
|
384
365
|
h.onFinal?.(data);
|
|
385
366
|
break;
|
|
367
|
+
case "visual":
|
|
368
|
+
h.onVisual?.(data);
|
|
369
|
+
break;
|
|
370
|
+
case "visuals_complete":
|
|
371
|
+
h.onVisualsComplete?.(data);
|
|
372
|
+
break;
|
|
386
373
|
case "error":
|
|
387
374
|
h.onError?.(data);
|
|
388
375
|
break;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@babav/knowledge-core-client/visual` — the babav.visual grammar TYPES.
|
|
3
|
+
*
|
|
4
|
+
* Types only (zero runtime, zero deps): they let a client type the visual payloads it may
|
|
5
|
+
* receive. All visual PROCESSING — grammar validation, layout, and SVG/PNG rendering — runs
|
|
6
|
+
* SERVER-SIDE in render-service; the client only displays the server-produced SVG/image.
|
|
7
|
+
* The schema + validators + renderers therefore live in render-service, not here.
|
|
8
|
+
*/
|
|
9
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@babav/knowledge-core-client/visual` — the babav.visual grammar TYPES.
|
|
3
|
+
*
|
|
4
|
+
* Types only (zero runtime, zero deps): they let a client type the visual payloads it may
|
|
5
|
+
* receive. All visual PROCESSING — grammar validation, layout, and SVG/PNG rendering — runs
|
|
6
|
+
* SERVER-SIDE in render-service; the client only displays the server-produced SVG/image.
|
|
7
|
+
* The schema + validators + renderers therefore live in render-service, not here.
|
|
8
|
+
*/
|
|
9
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `babav.visual` grammar — TypeScript types (WP1a).
|
|
3
|
+
*
|
|
4
|
+
* The typed structural-composition language the visual pipeline emits for the
|
|
5
|
+
* `structural` register (and the envelope that wraps every register's payload). Uses
|
|
6
|
+
* vocabulary models already know — nodes, connectors (edges), containers/panels
|
|
7
|
+
* (clusters), composition operators. LLMs compose in this grammar; a deterministic
|
|
8
|
+
* engine (ELK) does layout — models never emit coordinates.
|
|
9
|
+
*
|
|
10
|
+
* NB: the grammar uses its own camelCase convention (`chartBlock`, `vegaLiteSpec`,
|
|
11
|
+
* `focalElement`) per the visual spec — distinct from the KC API's snake_case wire
|
|
12
|
+
* shapes. Versioned from the first commit (`version: "1"`).
|
|
13
|
+
*/
|
|
14
|
+
export type VisualRegister = "chart" | "structural" | "conceptual" | "scenic";
|
|
15
|
+
export type EmphasisLevel = "normal" | "strong" | "muted";
|
|
16
|
+
export type ConnectorKind = "flow" | "dependency" | "association" | "containment" | "bidirectional";
|
|
17
|
+
export interface NodeElement {
|
|
18
|
+
type: "node";
|
|
19
|
+
id: string;
|
|
20
|
+
label: string;
|
|
21
|
+
role?: string;
|
|
22
|
+
emphasis?: EmphasisLevel;
|
|
23
|
+
}
|
|
24
|
+
export interface ConnectorElement {
|
|
25
|
+
type: "connector";
|
|
26
|
+
id?: string;
|
|
27
|
+
from: string;
|
|
28
|
+
to: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
kind: ConnectorKind;
|
|
31
|
+
}
|
|
32
|
+
export interface ContainerElement {
|
|
33
|
+
type: "container";
|
|
34
|
+
id: string;
|
|
35
|
+
label?: string;
|
|
36
|
+
children: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface PanelElement {
|
|
39
|
+
type: "panel";
|
|
40
|
+
id: string;
|
|
41
|
+
title?: string;
|
|
42
|
+
children: string[];
|
|
43
|
+
}
|
|
44
|
+
export interface AnnotationElement {
|
|
45
|
+
type: "annotation";
|
|
46
|
+
id?: string;
|
|
47
|
+
target: string;
|
|
48
|
+
text: string;
|
|
49
|
+
}
|
|
50
|
+
export interface ChartBlockElement {
|
|
51
|
+
type: "chartBlock";
|
|
52
|
+
id: string;
|
|
53
|
+
vegaLiteSpec: Record<string, unknown>;
|
|
54
|
+
}
|
|
55
|
+
export type VisualElement = NodeElement | ConnectorElement | ContainerElement | PanelElement | AnnotationElement | ChartBlockElement;
|
|
56
|
+
export interface NestComposition {
|
|
57
|
+
op: "nest";
|
|
58
|
+
parent: string;
|
|
59
|
+
children: string[];
|
|
60
|
+
}
|
|
61
|
+
export interface SequenceComposition {
|
|
62
|
+
op: "sequence";
|
|
63
|
+
items: string[];
|
|
64
|
+
}
|
|
65
|
+
export interface JuxtaposeComposition {
|
|
66
|
+
op: "juxtapose";
|
|
67
|
+
items: string[];
|
|
68
|
+
}
|
|
69
|
+
export interface LayerComposition {
|
|
70
|
+
op: "layer";
|
|
71
|
+
items: string[];
|
|
72
|
+
}
|
|
73
|
+
export interface LinkComposition {
|
|
74
|
+
op: "link";
|
|
75
|
+
from: string;
|
|
76
|
+
to: string;
|
|
77
|
+
label?: string;
|
|
78
|
+
kind?: ConnectorKind;
|
|
79
|
+
}
|
|
80
|
+
export type VisualComposition = NestComposition | SequenceComposition | JuxtaposeComposition | LayerComposition | LinkComposition;
|
|
81
|
+
export type Orientation = "horizontal" | "vertical" | "radial";
|
|
82
|
+
export type Density = "compact" | "comfortable" | "spacious";
|
|
83
|
+
export interface LayoutIntent {
|
|
84
|
+
orientation?: Orientation;
|
|
85
|
+
density?: Density;
|
|
86
|
+
focalElement?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface VisualPayload {
|
|
89
|
+
elements: VisualElement[];
|
|
90
|
+
composition?: VisualComposition[];
|
|
91
|
+
layout?: LayoutIntent;
|
|
92
|
+
}
|
|
93
|
+
/** Per-element source provenance. Present from v1; populated in Phase 2. */
|
|
94
|
+
export interface VisualProvenance {
|
|
95
|
+
[k: string]: unknown;
|
|
96
|
+
}
|
|
97
|
+
/** The envelope wrapping every register's payload. */
|
|
98
|
+
export interface VisualEnvelope {
|
|
99
|
+
schema: "babav.visual";
|
|
100
|
+
version: "1";
|
|
101
|
+
register: VisualRegister;
|
|
102
|
+
gist?: string;
|
|
103
|
+
provenance?: VisualProvenance[];
|
|
104
|
+
payload: VisualPayload;
|
|
105
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `babav.visual` grammar — TypeScript types (WP1a).
|
|
3
|
+
*
|
|
4
|
+
* The typed structural-composition language the visual pipeline emits for the
|
|
5
|
+
* `structural` register (and the envelope that wraps every register's payload). Uses
|
|
6
|
+
* vocabulary models already know — nodes, connectors (edges), containers/panels
|
|
7
|
+
* (clusters), composition operators. LLMs compose in this grammar; a deterministic
|
|
8
|
+
* engine (ELK) does layout — models never emit coordinates.
|
|
9
|
+
*
|
|
10
|
+
* NB: the grammar uses its own camelCase convention (`chartBlock`, `vegaLiteSpec`,
|
|
11
|
+
* `focalElement`) per the visual spec — distinct from the KC API's snake_case wire
|
|
12
|
+
* shapes. Versioned from the first commit (`version: "1"`).
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@babav/knowledge-core-client",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "TypeScript client for the Babav Knowledge Core API (Deno + Node 18+, zero deps).",
|
|
3
|
+
"version": "0.20.0",
|
|
4
|
+
"description": "TypeScript client for the Babav Knowledge Core API (Deno + Node 18+, zero deps). Includes the babav.visual grammar TYPES at the ./visual subpath (types only; all visual rendering is server-side).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -9,9 +9,16 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./visual": {
|
|
14
|
+
"types": "./dist/visual/index.d.ts",
|
|
15
|
+
"import": "./dist/visual/index.js"
|
|
12
16
|
}
|
|
13
17
|
},
|
|
14
|
-
"files": [
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src"
|
|
21
|
+
],
|
|
15
22
|
"publishConfig": {
|
|
16
23
|
"access": "public",
|
|
17
24
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -23,12 +30,15 @@
|
|
|
23
30
|
},
|
|
24
31
|
"scripts": {
|
|
25
32
|
"build": "tsc -p tsconfig.json",
|
|
26
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
33
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
34
|
+
"test": "npm run build && node --test test/"
|
|
27
35
|
},
|
|
28
36
|
"devDependencies": {
|
|
29
37
|
"typescript": "^5.6.0"
|
|
30
38
|
},
|
|
31
|
-
"engines": {
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18"
|
|
41
|
+
},
|
|
32
42
|
"sideEffects": false,
|
|
33
43
|
"private": false,
|
|
34
44
|
"license": "UNLICENSED"
|
package/src/index.ts
CHANGED
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
* key for all data ops; use AdminClient with the ADMIN key for tenant / API-key /
|
|
13
13
|
* agent management. The key is server-side only — never ship it to a browser.
|
|
14
14
|
*
|
|
15
|
-
* Configuration —
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `--allow-env` (without it, pass the values explicitly).
|
|
15
|
+
* Configuration — the CALLER supplies credentials at construction; the SDK never reads
|
|
16
|
+
* the environment or defaults/derives a key itself:
|
|
17
|
+
* new KnowledgeCoreClient({ baseUrl, apiKey }) // apiKey = a TENANT key
|
|
18
|
+
* new AdminClient({ baseUrl, apiKey }) // apiKey = the ADMIN key
|
|
19
|
+
* The app decides where its key comes from (its own env/secret store) and passes it in.
|
|
20
|
+
* A missing baseUrl or apiKey throws at construction with a clear message.
|
|
22
21
|
*/
|
|
23
22
|
|
|
24
23
|
// ---------------------------------------------------------------------------
|
|
@@ -26,6 +25,18 @@
|
|
|
26
25
|
// ---------------------------------------------------------------------------
|
|
27
26
|
export type UUID = string;
|
|
28
27
|
|
|
28
|
+
// The babav.visual grammar (WP1a). Types are re-exported here for convenience; the full
|
|
29
|
+
// grammar (schema + validators + fixtures) lives at the `./visual` subpath so it can pull
|
|
30
|
+
// its optional `ajv` peer without adding any dependency to this main entry.
|
|
31
|
+
export type {
|
|
32
|
+
VisualEnvelope,
|
|
33
|
+
VisualPayload,
|
|
34
|
+
VisualElement,
|
|
35
|
+
VisualComposition,
|
|
36
|
+
VisualRegister,
|
|
37
|
+
ChartBlockElement,
|
|
38
|
+
} from "./visual/types.js";
|
|
39
|
+
|
|
29
40
|
export interface Page<T> {
|
|
30
41
|
items: T[];
|
|
31
42
|
next_cursor: string | null;
|
|
@@ -76,12 +87,48 @@ export interface QueryOverrides {
|
|
|
76
87
|
citations_enabled?: boolean; // source attribution (default on)
|
|
77
88
|
}
|
|
78
89
|
|
|
90
|
+
/** Per-request visual overrides (see VisualRequest). */
|
|
91
|
+
export interface VisualOverrides {
|
|
92
|
+
concept_rounds_max?: number;
|
|
93
|
+
proposals_n?: number;
|
|
94
|
+
max_revisions?: number;
|
|
95
|
+
claims_check_model?: string;
|
|
96
|
+
vision_judge_model?: string;
|
|
97
|
+
scenic_enabled?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Per-request visual control. Absent => mode resolves from the agent default. All visual
|
|
101
|
+
* PROCESSING is server-side; the client only displays the result. */
|
|
102
|
+
export interface VisualRequest {
|
|
103
|
+
mode?: "off" | "on";
|
|
104
|
+
delivery?: "svg" | "json" | "both";
|
|
105
|
+
overrides?: VisualOverrides;
|
|
106
|
+
}
|
|
107
|
+
|
|
79
108
|
export interface QueryRequest {
|
|
80
109
|
corpus_ids: UUID[];
|
|
81
110
|
query: string;
|
|
82
111
|
conversation_id?: UUID | null; // present => conversational; absent => one-shot
|
|
83
112
|
overrides?: QueryOverrides;
|
|
84
113
|
filter?: MetadataFilter;
|
|
114
|
+
visual?: VisualRequest;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** A visual attached to a response, anchored by char offsets into `answer` (SAME coordinate
|
|
118
|
+
* system as citations). For delivery="svg", `rendered_svg` is set; scenic sets `image`. */
|
|
119
|
+
export interface Visual {
|
|
120
|
+
id: string;
|
|
121
|
+
anchor: { start: number; end: number };
|
|
122
|
+
register: "chart" | "structural" | "conceptual" | "scenic";
|
|
123
|
+
priority: number;
|
|
124
|
+
payload: Record<string, unknown>; // {kind: "grammar"|"vega_lite"|"svg"|"image", ...}
|
|
125
|
+
rendered_svg?: string;
|
|
126
|
+
image?: { url: string; expires_at: number; width: number; height: number };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface VisualsMeta {
|
|
130
|
+
count: number;
|
|
131
|
+
dropped: number;
|
|
85
132
|
}
|
|
86
133
|
|
|
87
134
|
export interface QueryResponse {
|
|
@@ -93,6 +140,8 @@ export interface QueryResponse {
|
|
|
93
140
|
groundedness: Groundedness | null;
|
|
94
141
|
usage: Record<string, number | null>;
|
|
95
142
|
standalone_query: string | null;
|
|
143
|
+
visuals?: Visual[]; // [] when off/none
|
|
144
|
+
visuals_meta?: VisualsMeta | null;
|
|
96
145
|
}
|
|
97
146
|
|
|
98
147
|
export interface Citation {
|
|
@@ -196,6 +245,7 @@ export interface Message {
|
|
|
196
245
|
groundedness: Record<string, unknown> | null;
|
|
197
246
|
retrieval_contents: unknown[] | null;
|
|
198
247
|
usage: Record<string, unknown> | null;
|
|
248
|
+
visuals?: { items: Visual[]; meta: VisualsMeta } | null; // post-generation visuals (re-signed URLs on read)
|
|
199
249
|
}
|
|
200
250
|
export interface Attachment {
|
|
201
251
|
id: UUID;
|
|
@@ -279,34 +329,16 @@ export class KnowledgeCoreError extends Error {
|
|
|
279
329
|
// Base HTTP
|
|
280
330
|
// ---------------------------------------------------------------------------
|
|
281
331
|
export interface ClientOptions {
|
|
282
|
-
/** API base URL
|
|
283
|
-
baseUrl
|
|
284
|
-
/**
|
|
285
|
-
*
|
|
286
|
-
apiKey
|
|
332
|
+
/** API base URL — REQUIRED, supplied by the caller. */
|
|
333
|
+
baseUrl: string;
|
|
334
|
+
/** API key — REQUIRED, supplied by the caller (a TENANT key for KnowledgeCoreClient,
|
|
335
|
+
* the ADMIN key for AdminClient). The SDK never reads it from the environment. */
|
|
336
|
+
apiKey: string;
|
|
287
337
|
/** Optional default fetch timeout (ms). Streaming ignores this. */
|
|
288
338
|
timeoutMs?: number;
|
|
289
339
|
fetch?: typeof fetch; // override for tests
|
|
290
340
|
}
|
|
291
341
|
|
|
292
|
-
/** Read an env var under Node (process.env) or Deno (Deno.env); undefined if unset
|
|
293
|
-
* or inaccessible (e.g. Deno without --allow-env). */
|
|
294
|
-
function readEnv(name: string): string | undefined {
|
|
295
|
-
const g = globalThis as {
|
|
296
|
-
process?: { env?: Record<string, string | undefined> };
|
|
297
|
-
Deno?: { env?: { get?: (n: string) => string | undefined } };
|
|
298
|
-
};
|
|
299
|
-
const fromNode = g.process?.env?.[name];
|
|
300
|
-
if (fromNode) return fromNode;
|
|
301
|
-
try {
|
|
302
|
-
const fromDeno = g.Deno?.env?.get?.(name);
|
|
303
|
-
if (fromDeno) return fromDeno;
|
|
304
|
-
} catch {
|
|
305
|
-
/* Deno env access denied (no --allow-env) — treat as unset */
|
|
306
|
-
}
|
|
307
|
-
return undefined;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
342
|
interface RequestOpts {
|
|
311
343
|
query?: Record<string, string | number | boolean | undefined>;
|
|
312
344
|
json?: unknown;
|
|
@@ -321,13 +353,12 @@ class HttpBase {
|
|
|
321
353
|
protected readonly timeoutMs?: number;
|
|
322
354
|
protected readonly _fetch: typeof fetch;
|
|
323
355
|
|
|
324
|
-
constructor(opts: ClientOptions
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (!
|
|
328
|
-
|
|
329
|
-
this.
|
|
330
|
-
this.apiKey = apiKey;
|
|
356
|
+
constructor(opts: ClientOptions) {
|
|
357
|
+
// Credentials come from the CALLER at init — the SDK never sources a key itself.
|
|
358
|
+
if (!opts?.baseUrl) throw new Error("KnowledgeCore: { baseUrl } is required");
|
|
359
|
+
if (!opts?.apiKey) throw new Error("KnowledgeCore: { apiKey } is required — the caller must supply the key at init");
|
|
360
|
+
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
361
|
+
this.apiKey = opts.apiKey;
|
|
331
362
|
this.timeoutMs = opts.timeoutMs;
|
|
332
363
|
this._fetch = opts.fetch ?? fetch;
|
|
333
364
|
}
|
|
@@ -425,6 +456,11 @@ export interface StreamHandlers {
|
|
|
425
456
|
* (native path). Also present in `final`. May be `{}` if scoring was unavailable. */
|
|
426
457
|
onGroundedness?: (g: Groundedness | Record<string, never>) => void;
|
|
427
458
|
onFinal?: (d: QueryResponse) => void;
|
|
459
|
+
/** A visual, emitted (out of anchor order) during the trailing visual phase when
|
|
460
|
+
* visual.mode="on". Place by `anchor`, not arrival order. */
|
|
461
|
+
onVisual?: (v: Visual) => void;
|
|
462
|
+
/** Always emitted exactly once to close the visual phase (incl. count=0), before `done`. */
|
|
463
|
+
onVisualsComplete?: (m: VisualsMeta) => void;
|
|
428
464
|
onError?: (d: unknown) => void;
|
|
429
465
|
onDone?: () => void;
|
|
430
466
|
/** Catch-all for any event (incl. unknown ones). */
|
|
@@ -435,9 +471,9 @@ export interface StreamHandlers {
|
|
|
435
471
|
// Tenant client (data ops) — use a TENANT key
|
|
436
472
|
// ---------------------------------------------------------------------------
|
|
437
473
|
export class KnowledgeCoreClient extends HttpBase {
|
|
438
|
-
/**
|
|
439
|
-
constructor(opts: ClientOptions
|
|
440
|
-
super(opts
|
|
474
|
+
/** @param opts.apiKey a TENANT key, supplied by the caller. */
|
|
475
|
+
constructor(opts: ClientOptions) {
|
|
476
|
+
super(opts);
|
|
441
477
|
}
|
|
442
478
|
|
|
443
479
|
// --- query (agent-anchored) ---
|
|
@@ -627,9 +663,9 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
627
663
|
// Admin client (tenant + key + agent management) — use the ADMIN key
|
|
628
664
|
// ---------------------------------------------------------------------------
|
|
629
665
|
export class AdminClient extends HttpBase {
|
|
630
|
-
/**
|
|
631
|
-
constructor(opts: ClientOptions
|
|
632
|
-
super(opts
|
|
666
|
+
/** @param opts.apiKey the ADMIN key, supplied by the caller. */
|
|
667
|
+
constructor(opts: ClientOptions) {
|
|
668
|
+
super(opts);
|
|
633
669
|
}
|
|
634
670
|
|
|
635
671
|
tenants = {
|
|
@@ -673,6 +709,8 @@ function dispatchSse(frame: string, h: StreamHandlers): void {
|
|
|
673
709
|
case "citation": h.onCitation?.(data as Citation); break;
|
|
674
710
|
case "groundedness": h.onGroundedness?.(data as never); break;
|
|
675
711
|
case "final": h.onFinal?.(data as QueryResponse); break;
|
|
712
|
+
case "visual": h.onVisual?.(data as Visual); break;
|
|
713
|
+
case "visuals_complete": h.onVisualsComplete?.(data as VisualsMeta); break;
|
|
676
714
|
case "error": h.onError?.(data); break;
|
|
677
715
|
case "done": h.onDone?.(); break;
|
|
678
716
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@babav/knowledge-core-client/visual` — the babav.visual grammar TYPES.
|
|
3
|
+
*
|
|
4
|
+
* Types only (zero runtime, zero deps): they let a client type the visual payloads it may
|
|
5
|
+
* receive. All visual PROCESSING — grammar validation, layout, and SVG/PNG rendering — runs
|
|
6
|
+
* SERVER-SIDE in render-service; the client only displays the server-produced SVG/image.
|
|
7
|
+
* The schema + validators + renderers therefore live in render-service, not here.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `babav.visual` grammar — TypeScript types (WP1a).
|
|
3
|
+
*
|
|
4
|
+
* The typed structural-composition language the visual pipeline emits for the
|
|
5
|
+
* `structural` register (and the envelope that wraps every register's payload). Uses
|
|
6
|
+
* vocabulary models already know — nodes, connectors (edges), containers/panels
|
|
7
|
+
* (clusters), composition operators. LLMs compose in this grammar; a deterministic
|
|
8
|
+
* engine (ELK) does layout — models never emit coordinates.
|
|
9
|
+
*
|
|
10
|
+
* NB: the grammar uses its own camelCase convention (`chartBlock`, `vegaLiteSpec`,
|
|
11
|
+
* `focalElement`) per the visual spec — distinct from the KC API's snake_case wire
|
|
12
|
+
* shapes. Versioned from the first commit (`version: "1"`).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export type VisualRegister = "chart" | "structural" | "conceptual" | "scenic";
|
|
16
|
+
|
|
17
|
+
export type EmphasisLevel = "normal" | "strong" | "muted";
|
|
18
|
+
export type ConnectorKind =
|
|
19
|
+
| "flow"
|
|
20
|
+
| "dependency"
|
|
21
|
+
| "association"
|
|
22
|
+
| "containment"
|
|
23
|
+
| "bidirectional";
|
|
24
|
+
|
|
25
|
+
// --- Layer A: primitives (each drawable element; `type`-discriminated) --------
|
|
26
|
+
export interface NodeElement {
|
|
27
|
+
type: "node";
|
|
28
|
+
id: string;
|
|
29
|
+
label: string;
|
|
30
|
+
role?: string;
|
|
31
|
+
emphasis?: EmphasisLevel;
|
|
32
|
+
}
|
|
33
|
+
export interface ConnectorElement {
|
|
34
|
+
type: "connector";
|
|
35
|
+
id?: string;
|
|
36
|
+
from: string; // node id
|
|
37
|
+
to: string; // node id
|
|
38
|
+
label?: string;
|
|
39
|
+
kind: ConnectorKind;
|
|
40
|
+
}
|
|
41
|
+
export interface ContainerElement {
|
|
42
|
+
type: "container";
|
|
43
|
+
id: string;
|
|
44
|
+
label?: string;
|
|
45
|
+
children: string[]; // element ids
|
|
46
|
+
}
|
|
47
|
+
export interface PanelElement {
|
|
48
|
+
type: "panel";
|
|
49
|
+
id: string;
|
|
50
|
+
title?: string;
|
|
51
|
+
children: string[]; // element ids
|
|
52
|
+
}
|
|
53
|
+
export interface AnnotationElement {
|
|
54
|
+
type: "annotation";
|
|
55
|
+
id?: string;
|
|
56
|
+
target: string; // element id
|
|
57
|
+
text: string;
|
|
58
|
+
}
|
|
59
|
+
export interface ChartBlockElement {
|
|
60
|
+
type: "chartBlock";
|
|
61
|
+
id: string;
|
|
62
|
+
vegaLiteSpec: Record<string, unknown>; // whitelisted subset enforced at render time
|
|
63
|
+
}
|
|
64
|
+
export type VisualElement =
|
|
65
|
+
| NodeElement
|
|
66
|
+
| ConnectorElement
|
|
67
|
+
| ContainerElement
|
|
68
|
+
| PanelElement
|
|
69
|
+
| AnnotationElement
|
|
70
|
+
| ChartBlockElement;
|
|
71
|
+
|
|
72
|
+
// --- Layer B: composition (arrangement over element ids; `op`-discriminated) --
|
|
73
|
+
export interface NestComposition {
|
|
74
|
+
op: "nest";
|
|
75
|
+
parent: string;
|
|
76
|
+
children: string[];
|
|
77
|
+
}
|
|
78
|
+
export interface SequenceComposition {
|
|
79
|
+
op: "sequence";
|
|
80
|
+
items: string[];
|
|
81
|
+
}
|
|
82
|
+
export interface JuxtaposeComposition {
|
|
83
|
+
op: "juxtapose";
|
|
84
|
+
items: string[];
|
|
85
|
+
}
|
|
86
|
+
export interface LayerComposition {
|
|
87
|
+
op: "layer";
|
|
88
|
+
items: string[];
|
|
89
|
+
}
|
|
90
|
+
export interface LinkComposition {
|
|
91
|
+
op: "link";
|
|
92
|
+
from: string;
|
|
93
|
+
to: string;
|
|
94
|
+
label?: string;
|
|
95
|
+
kind?: ConnectorKind;
|
|
96
|
+
}
|
|
97
|
+
export type VisualComposition =
|
|
98
|
+
| NestComposition
|
|
99
|
+
| SequenceComposition
|
|
100
|
+
| JuxtaposeComposition
|
|
101
|
+
| LayerComposition
|
|
102
|
+
| LinkComposition;
|
|
103
|
+
|
|
104
|
+
// --- Layout intent: hints only; the engine decides -------------------------
|
|
105
|
+
export type Orientation = "horizontal" | "vertical" | "radial";
|
|
106
|
+
export type Density = "compact" | "comfortable" | "spacious";
|
|
107
|
+
export interface LayoutIntent {
|
|
108
|
+
orientation?: Orientation;
|
|
109
|
+
density?: Density;
|
|
110
|
+
focalElement?: string; // element id
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface VisualPayload {
|
|
114
|
+
elements: VisualElement[];
|
|
115
|
+
composition?: VisualComposition[];
|
|
116
|
+
layout?: LayoutIntent;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Per-element source provenance. Present from v1; populated in Phase 2. */
|
|
120
|
+
export interface VisualProvenance {
|
|
121
|
+
[k: string]: unknown;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** The envelope wrapping every register's payload. */
|
|
125
|
+
export interface VisualEnvelope {
|
|
126
|
+
schema: "babav.visual";
|
|
127
|
+
version: "1";
|
|
128
|
+
register: VisualRegister;
|
|
129
|
+
gist?: string;
|
|
130
|
+
provenance?: VisualProvenance[];
|
|
131
|
+
payload: VisualPayload;
|
|
132
|
+
}
|