@babav/knowledge-core-client 0.31.0 → 0.32.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/dist/index.d.ts CHANGED
@@ -97,13 +97,11 @@ export type VisualLayout = "linear-flow" | "ring-cycle" | "nesting" | "radial-hu
97
97
  /** A visual attached to a response, anchored by char offsets into `answer` (SAME coordinate
98
98
  * system as citations).
99
99
  *
100
- * UNIFORM DELIVERY: every register (chart / structural / conceptual / scenic) carries `image` — a
101
- * PNG served BY KC. To display it, GET `image.url` (resolve a relative path against your KC base
102
- * URL) with your normal API key; the response body is the PNG bytes. The URL is a stable, non-
103
- * expiring KC endpoint for persisted/conversational visuals (`expires_at` absent), so it works on
104
- * reload/copy/export and on later conversation retrieval the client never fetches GCS and never
105
- * parses inline SVG. `rendered_svg` appears ONLY as a rare fail-soft fallback (server rasterization
106
- * failed); prefer `image` and treat `rendered_svg` as a last resort. */
100
+ * IDs-ONLY: the API never returns a URL. Every visual (chart / structural / conceptual / scenic) is
101
+ * a PNG served by KC and identified by its `id`. To display it, fetch the bytes by id:
102
+ * `getVisualImage(visual.id)` (or GET /v1/visuals/{id}/image with your API key). `image` carries only
103
+ * the pixel DIMENSIONS, for layout. The image is authenticated + tenant-scoped exactly like every
104
+ * other KC call; there is no URL, no signed GCS link, and nothing to expire. */
107
105
  export interface Visual {
108
106
  id: string;
109
107
  anchor: {
@@ -115,15 +113,11 @@ export interface Visual {
115
113
  payload: Record<string, unknown>;
116
114
  /** Declared spatial arrangement (meaningful for `conceptual`; "free" otherwise). */
117
115
  layout: VisualLayout;
118
- /** PRIMARY: GET this (relative to your KC base, with your API key) -> PNG bytes. */
116
+ /** Pixel dimensions of the PNG (for layout). Fetch the bytes with getVisualImage(id). */
119
117
  image?: {
120
- url: string;
121
118
  width: number;
122
119
  height: number;
123
- expires_at?: number;
124
120
  };
125
- /** Fail-soft fallback only (rasterize/store failed); normally absent. */
126
- rendered_svg?: string;
127
121
  }
128
122
  /** Visual stage (streaming): generation has started. MAY be emitted twice — first with
129
123
  * `pending: null` (started, count unknown), then again with the ACCURATE post-vet count before
@@ -541,6 +535,11 @@ export declare class KnowledgeCoreClient extends HttpBase {
541
535
  * error). Pass `signal` and abort() on unmount / when the user cancels or navigates away so the
542
536
  * connection doesn't linger. Transient (ends on `done`) — no reopen logic needed. */
543
537
  queryStream(agentId: UUID, body: QueryRequest, handlers: StreamHandlers, signal?: AbortSignal): Promise<void>;
538
+ /** Fetch a visual's PNG bytes BY ID. This is the ONLY way to get a visual image — the API never
539
+ * returns a URL. Authenticated + tenant-scoped like every call. Use `visual.id` from a query
540
+ * response / streamed `visual` event / persisted message. Returns a Blob (browser: `URL.
541
+ * createObjectURL(blob)` for an <img>; Node: `Buffer.from(await blob.arrayBuffer())`). */
542
+ getVisualImage(visualId: UUID | string, signal?: AbortSignal): Promise<Blob>;
544
543
  /** DUMMY-PROOF CHAT. Every message goes through a conversation — it is structurally impossible
545
544
  * to send a chat turn as a non-persisted one-shot. Use this for ANY chat UI. Use the low-level
546
545
  * `query`/`queryStream` ONLY for programmatic one-shots (tools).
package/dist/index.js CHANGED
@@ -178,6 +178,18 @@ export class KnowledgeCoreClient extends HttpBase {
178
178
  if (buf.trim())
179
179
  dispatchSse(buf, handlers);
180
180
  }
181
+ /** Fetch a visual's PNG bytes BY ID. This is the ONLY way to get a visual image — the API never
182
+ * returns a URL. Authenticated + tenant-scoped like every call. Use `visual.id` from a query
183
+ * response / streamed `visual` event / persisted message. Returns a Blob (browser: `URL.
184
+ * createObjectURL(blob)` for an <img>; Node: `Buffer.from(await blob.arrayBuffer())`). */
185
+ async getVisualImage(visualId, signal) {
186
+ const res = await this.raw("GET", `/v1/visuals/${visualId}/image`, { signal });
187
+ if (!res.ok) {
188
+ const t = await res.text();
189
+ throw new KnowledgeCoreError(res.status, safeJson(t), `/v1/visuals/${visualId}/image`);
190
+ }
191
+ return await res.blob();
192
+ }
181
193
  /** DUMMY-PROOF CHAT. Every message goes through a conversation — it is structurally impossible
182
194
  * to send a chat turn as a non-persisted one-shot. Use this for ANY chat UI. Use the low-level
183
195
  * `query`/`queryStream` ONLY for programmatic one-shots (tools).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babav/knowledge-core-client",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
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",
package/src/index.ts CHANGED
@@ -131,25 +131,21 @@ export type VisualLayout =
131
131
  /** A visual attached to a response, anchored by char offsets into `answer` (SAME coordinate
132
132
  * system as citations).
133
133
  *
134
- * UNIFORM DELIVERY: every register (chart / structural / conceptual / scenic) carries `image` — a
135
- * PNG served BY KC. To display it, GET `image.url` (resolve a relative path against your KC base
136
- * URL) with your normal API key; the response body is the PNG bytes. The URL is a stable, non-
137
- * expiring KC endpoint for persisted/conversational visuals (`expires_at` absent), so it works on
138
- * reload/copy/export and on later conversation retrieval the client never fetches GCS and never
139
- * parses inline SVG. `rendered_svg` appears ONLY as a rare fail-soft fallback (server rasterization
140
- * failed); prefer `image` and treat `rendered_svg` as a last resort. */
134
+ * IDs-ONLY: the API never returns a URL. Every visual (chart / structural / conceptual / scenic) is
135
+ * a PNG served by KC and identified by its `id`. To display it, fetch the bytes by id:
136
+ * `getVisualImage(visual.id)` (or GET /v1/visuals/{id}/image with your API key). `image` carries only
137
+ * the pixel DIMENSIONS, for layout. The image is authenticated + tenant-scoped exactly like every
138
+ * other KC call; there is no URL, no signed GCS link, and nothing to expire. */
141
139
  export interface Visual {
142
140
  id: string;
143
141
  anchor: { start: number; end: number };
144
142
  register: "chart" | "structural" | "conceptual" | "scenic";
145
143
  priority: number;
146
- payload: Record<string, unknown>; // {kind: "grammar"|"vega_lite"|"svg"|"image", ...}
144
+ payload: Record<string, unknown>; // {kind: "grammar"|"vega_lite"|"image", ...}
147
145
  /** Declared spatial arrangement (meaningful for `conceptual`; "free" otherwise). */
148
146
  layout: VisualLayout;
149
- /** PRIMARY: GET this (relative to your KC base, with your API key) -> PNG bytes. */
150
- image?: { url: string; width: number; height: number; expires_at?: number };
151
- /** Fail-soft fallback only (rasterize/store failed); normally absent. */
152
- rendered_svg?: string;
147
+ /** Pixel dimensions of the PNG (for layout). Fetch the bytes with getVisualImage(id). */
148
+ image?: { width: number; height: number };
153
149
  }
154
150
 
155
151
  /** Visual stage (streaming): generation has started. MAY be emitted twice — first with
@@ -655,6 +651,19 @@ export class KnowledgeCoreClient extends HttpBase {
655
651
  if (buf.trim()) dispatchSse(buf, handlers);
656
652
  }
657
653
 
654
+ /** Fetch a visual's PNG bytes BY ID. This is the ONLY way to get a visual image — the API never
655
+ * returns a URL. Authenticated + tenant-scoped like every call. Use `visual.id` from a query
656
+ * response / streamed `visual` event / persisted message. Returns a Blob (browser: `URL.
657
+ * createObjectURL(blob)` for an <img>; Node: `Buffer.from(await blob.arrayBuffer())`). */
658
+ async getVisualImage(visualId: UUID | string, signal?: AbortSignal): Promise<Blob> {
659
+ const res = await this.raw("GET", `/v1/visuals/${visualId}/image`, { signal });
660
+ if (!res.ok) {
661
+ const t = await res.text();
662
+ throw new KnowledgeCoreError(res.status, safeJson(t), `/v1/visuals/${visualId}/image`);
663
+ }
664
+ return await res.blob();
665
+ }
666
+
658
667
  /** DUMMY-PROOF CHAT. Every message goes through a conversation — it is structurally impossible
659
668
  * to send a chat turn as a non-persisted one-shot. Use this for ANY chat UI. Use the low-level
660
669
  * `query`/`queryStream` ONLY for programmatic one-shots (tools).