@babav/knowledge-core-client 0.29.0 → 0.30.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 +44 -0
- package/dist/index.js +54 -0
- package/package.json +1 -1
- package/src/index.ts +79 -0
package/dist/index.d.ts
CHANGED
|
@@ -531,6 +531,16 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
531
531
|
* error). Pass `signal` and abort() on unmount / when the user cancels or navigates away so the
|
|
532
532
|
* connection doesn't linger. Transient (ends on `done`) — no reopen logic needed. */
|
|
533
533
|
queryStream(agentId: UUID, body: QueryRequest, handlers: StreamHandlers, signal?: AbortSignal): Promise<void>;
|
|
534
|
+
/** DUMMY-PROOF CHAT. Every message goes through a conversation — it is structurally impossible
|
|
535
|
+
* to send a chat turn as a non-persisted one-shot. Use this for ANY chat UI. Use the low-level
|
|
536
|
+
* `query`/`queryStream` ONLY for programmatic one-shots (tools).
|
|
537
|
+
* New chat: const chat = kc.chat(agentId, corpusIds);
|
|
538
|
+
* Resume: const chat = kc.chat(agentId, corpusIds, { conversationId });
|
|
539
|
+
* The conversation is created LAZILY on the first `send()` (opening a "new chat" and never
|
|
540
|
+
* sending leaves nothing behind). See ChatSession.send. */
|
|
541
|
+
chat(agentId: UUID, corpusIds: UUID[], opts?: {
|
|
542
|
+
conversationId?: UUID;
|
|
543
|
+
}): ChatSession;
|
|
534
544
|
/** Shared SSE reader for the document-status streams (documents.events / folders.events).
|
|
535
545
|
* Resolves when the stream ends (server sends `complete` once nothing is in-flight, or the
|
|
536
546
|
* cap is hit). Abort via the signal to stop watching. Throws 501 if the env has no bus. */
|
|
@@ -896,3 +906,37 @@ export declare class AdminClient extends HttpBase {
|
|
|
896
906
|
delete: (id: UUID) => Promise<void>;
|
|
897
907
|
};
|
|
898
908
|
}
|
|
909
|
+
export interface ChatSendOptions extends StreamHandlers {
|
|
910
|
+
overrides?: QueryRequest["overrides"];
|
|
911
|
+
filter?: QueryRequest["filter"];
|
|
912
|
+
visual?: QueryRequest["visual"];
|
|
913
|
+
/** Abort on unmount / navigation so the SSE connection doesn't linger. */
|
|
914
|
+
signal?: AbortSignal;
|
|
915
|
+
/** Applied ONLY when the conversation is lazily created on the FIRST message. `title` defaults
|
|
916
|
+
* to the message text (truncated) so a chat is never left untitled. */
|
|
917
|
+
title?: string;
|
|
918
|
+
customMetadata?: Record<string, unknown>;
|
|
919
|
+
ephemeral?: boolean;
|
|
920
|
+
/** Fired with the conversation id the moment it is created (first message) or resumed — use it to
|
|
921
|
+
* update the sidebar/URL/route IMMEDIATELY, before the answer streams. */
|
|
922
|
+
onConversationId?: (id: UUID) => void;
|
|
923
|
+
}
|
|
924
|
+
/** A chat session bound to ONE conversation (created via `kc.chat(...)`). Every `send()` is ALWAYS
|
|
925
|
+
* conversational: the conversation_id is attached for you, so a chat turn can never be a
|
|
926
|
+
* non-persisted one-shot. Combined with server-side persist-on-close salvage + the orphan reaper,
|
|
927
|
+
* a chat turn is never lost and a chat conversation is never left blank. */
|
|
928
|
+
export declare class ChatSession {
|
|
929
|
+
#private;
|
|
930
|
+
/** The conversation id — null until the first `send()` (unless resumed). */
|
|
931
|
+
conversationId: UUID | null;
|
|
932
|
+
constructor(kc: KnowledgeCoreClient, agentId: UUID, corpusIds: UUID[], conversationId: UUID | null);
|
|
933
|
+
/** Send a chat message (streaming). Lazily creates the conversation on the first message and
|
|
934
|
+
* ALWAYS passes conversation_id, so the turn is persisted. `onConversationId` fires before the
|
|
935
|
+
* stream so you can show the conversation immediately. Pass `signal` to cancel on unmount. */
|
|
936
|
+
send(text: string, o?: ChatSendOptions): Promise<void>;
|
|
937
|
+
/** The conversation history (messages), once it exists. Empty page before the first send. */
|
|
938
|
+
messages(q?: {
|
|
939
|
+
limit?: number;
|
|
940
|
+
cursor?: string;
|
|
941
|
+
}): Promise<Page<Message>>;
|
|
942
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -178,6 +178,16 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
178
178
|
if (buf.trim())
|
|
179
179
|
dispatchSse(buf, handlers);
|
|
180
180
|
}
|
|
181
|
+
/** DUMMY-PROOF CHAT. Every message goes through a conversation — it is structurally impossible
|
|
182
|
+
* to send a chat turn as a non-persisted one-shot. Use this for ANY chat UI. Use the low-level
|
|
183
|
+
* `query`/`queryStream` ONLY for programmatic one-shots (tools).
|
|
184
|
+
* New chat: const chat = kc.chat(agentId, corpusIds);
|
|
185
|
+
* Resume: const chat = kc.chat(agentId, corpusIds, { conversationId });
|
|
186
|
+
* The conversation is created LAZILY on the first `send()` (opening a "new chat" and never
|
|
187
|
+
* sending leaves nothing behind). See ChatSession.send. */
|
|
188
|
+
chat(agentId, corpusIds, opts) {
|
|
189
|
+
return new ChatSession(this, agentId, corpusIds, opts?.conversationId ?? null);
|
|
190
|
+
}
|
|
181
191
|
/** Shared SSE reader for the document-status streams (documents.events / folders.events).
|
|
182
192
|
* Resolves when the stream ends (server sends `complete` once nothing is in-flight, or the
|
|
183
193
|
* cap is hit). Abort via the signal to stop watching. Throws 501 if the env has no bus. */
|
|
@@ -460,6 +470,50 @@ export class AdminClient extends HttpBase {
|
|
|
460
470
|
delete: (id) => this.request("DELETE", `/v1/agents/${id}`),
|
|
461
471
|
};
|
|
462
472
|
}
|
|
473
|
+
/** A chat session bound to ONE conversation (created via `kc.chat(...)`). Every `send()` is ALWAYS
|
|
474
|
+
* conversational: the conversation_id is attached for you, so a chat turn can never be a
|
|
475
|
+
* non-persisted one-shot. Combined with server-side persist-on-close salvage + the orphan reaper,
|
|
476
|
+
* a chat turn is never lost and a chat conversation is never left blank. */
|
|
477
|
+
export class ChatSession {
|
|
478
|
+
#kc;
|
|
479
|
+
#agentId;
|
|
480
|
+
#corpusIds;
|
|
481
|
+
#creating = null;
|
|
482
|
+
/** The conversation id — null until the first `send()` (unless resumed). */
|
|
483
|
+
conversationId;
|
|
484
|
+
constructor(kc, agentId, corpusIds, conversationId) {
|
|
485
|
+
this.#kc = kc;
|
|
486
|
+
this.#agentId = agentId;
|
|
487
|
+
this.#corpusIds = corpusIds;
|
|
488
|
+
this.conversationId = conversationId;
|
|
489
|
+
}
|
|
490
|
+
/** Lazy create-once (concurrency-safe): the first send starts creation; a racing send awaits it. */
|
|
491
|
+
#ensure(o, text) {
|
|
492
|
+
if (this.conversationId)
|
|
493
|
+
return Promise.resolve(this.conversationId);
|
|
494
|
+
if (!this.#creating) {
|
|
495
|
+
this.#creating = this.#kc.conversations
|
|
496
|
+
.create({ title: o.title ?? text.slice(0, 80), custom_metadata: o.customMetadata, ephemeral: o.ephemeral })
|
|
497
|
+
.then((c) => { this.conversationId = c.id; return c.id; });
|
|
498
|
+
}
|
|
499
|
+
return this.#creating;
|
|
500
|
+
}
|
|
501
|
+
/** Send a chat message (streaming). Lazily creates the conversation on the first message and
|
|
502
|
+
* ALWAYS passes conversation_id, so the turn is persisted. `onConversationId` fires before the
|
|
503
|
+
* stream so you can show the conversation immediately. Pass `signal` to cancel on unmount. */
|
|
504
|
+
async send(text, o = {}) {
|
|
505
|
+
const convId = await this.#ensure(o, text);
|
|
506
|
+
o.onConversationId?.(convId);
|
|
507
|
+
await this.#kc.queryStream(this.#agentId, { corpus_ids: this.#corpusIds, query: text, conversation_id: convId,
|
|
508
|
+
overrides: o.overrides, filter: o.filter, visual: o.visual }, o, o.signal);
|
|
509
|
+
}
|
|
510
|
+
/** The conversation history (messages), once it exists. Empty page before the first send. */
|
|
511
|
+
messages(q) {
|
|
512
|
+
if (!this.conversationId)
|
|
513
|
+
return Promise.resolve({ items: [], next_cursor: null });
|
|
514
|
+
return this.#kc.conversations.listMessages(this.conversationId, q);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
463
517
|
// ---------------------------------------------------------------------------
|
|
464
518
|
// helpers
|
|
465
519
|
// ---------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@babav/knowledge-core-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.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
|
@@ -645,6 +645,17 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
645
645
|
if (buf.trim()) dispatchSse(buf, handlers);
|
|
646
646
|
}
|
|
647
647
|
|
|
648
|
+
/** DUMMY-PROOF CHAT. Every message goes through a conversation — it is structurally impossible
|
|
649
|
+
* to send a chat turn as a non-persisted one-shot. Use this for ANY chat UI. Use the low-level
|
|
650
|
+
* `query`/`queryStream` ONLY for programmatic one-shots (tools).
|
|
651
|
+
* New chat: const chat = kc.chat(agentId, corpusIds);
|
|
652
|
+
* Resume: const chat = kc.chat(agentId, corpusIds, { conversationId });
|
|
653
|
+
* The conversation is created LAZILY on the first `send()` (opening a "new chat" and never
|
|
654
|
+
* sending leaves nothing behind). See ChatSession.send. */
|
|
655
|
+
chat(agentId: UUID, corpusIds: UUID[], opts?: { conversationId?: UUID }): ChatSession {
|
|
656
|
+
return new ChatSession(this, agentId, corpusIds, opts?.conversationId ?? null);
|
|
657
|
+
}
|
|
658
|
+
|
|
648
659
|
/** Shared SSE reader for the document-status streams (documents.events / folders.events).
|
|
649
660
|
* Resolves when the stream ends (server sends `complete` once nothing is in-flight, or the
|
|
650
661
|
* cap is hit). Abort via the signal to stop watching. Throws 501 if the env has no bus. */
|
|
@@ -1001,6 +1012,74 @@ export class AdminClient extends HttpBase {
|
|
|
1001
1012
|
};
|
|
1002
1013
|
}
|
|
1003
1014
|
|
|
1015
|
+
export interface ChatSendOptions extends StreamHandlers {
|
|
1016
|
+
overrides?: QueryRequest["overrides"];
|
|
1017
|
+
filter?: QueryRequest["filter"];
|
|
1018
|
+
visual?: QueryRequest["visual"];
|
|
1019
|
+
/** Abort on unmount / navigation so the SSE connection doesn't linger. */
|
|
1020
|
+
signal?: AbortSignal;
|
|
1021
|
+
/** Applied ONLY when the conversation is lazily created on the FIRST message. `title` defaults
|
|
1022
|
+
* to the message text (truncated) so a chat is never left untitled. */
|
|
1023
|
+
title?: string;
|
|
1024
|
+
customMetadata?: Record<string, unknown>;
|
|
1025
|
+
ephemeral?: boolean;
|
|
1026
|
+
/** Fired with the conversation id the moment it is created (first message) or resumed — use it to
|
|
1027
|
+
* update the sidebar/URL/route IMMEDIATELY, before the answer streams. */
|
|
1028
|
+
onConversationId?: (id: UUID) => void;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/** A chat session bound to ONE conversation (created via `kc.chat(...)`). Every `send()` is ALWAYS
|
|
1032
|
+
* conversational: the conversation_id is attached for you, so a chat turn can never be a
|
|
1033
|
+
* non-persisted one-shot. Combined with server-side persist-on-close salvage + the orphan reaper,
|
|
1034
|
+
* a chat turn is never lost and a chat conversation is never left blank. */
|
|
1035
|
+
export class ChatSession {
|
|
1036
|
+
#kc: KnowledgeCoreClient;
|
|
1037
|
+
#agentId: UUID;
|
|
1038
|
+
#corpusIds: UUID[];
|
|
1039
|
+
#creating: Promise<UUID> | null = null;
|
|
1040
|
+
/** The conversation id — null until the first `send()` (unless resumed). */
|
|
1041
|
+
conversationId: UUID | null;
|
|
1042
|
+
|
|
1043
|
+
constructor(kc: KnowledgeCoreClient, agentId: UUID, corpusIds: UUID[], conversationId: UUID | null) {
|
|
1044
|
+
this.#kc = kc;
|
|
1045
|
+
this.#agentId = agentId;
|
|
1046
|
+
this.#corpusIds = corpusIds;
|
|
1047
|
+
this.conversationId = conversationId;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
/** Lazy create-once (concurrency-safe): the first send starts creation; a racing send awaits it. */
|
|
1051
|
+
#ensure(o: ChatSendOptions, text: string): Promise<UUID> {
|
|
1052
|
+
if (this.conversationId) return Promise.resolve(this.conversationId);
|
|
1053
|
+
if (!this.#creating) {
|
|
1054
|
+
this.#creating = this.#kc.conversations
|
|
1055
|
+
.create({ title: o.title ?? text.slice(0, 80), custom_metadata: o.customMetadata, ephemeral: o.ephemeral })
|
|
1056
|
+
.then((c) => { this.conversationId = c.id; return c.id; });
|
|
1057
|
+
}
|
|
1058
|
+
return this.#creating;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/** Send a chat message (streaming). Lazily creates the conversation on the first message and
|
|
1062
|
+
* ALWAYS passes conversation_id, so the turn is persisted. `onConversationId` fires before the
|
|
1063
|
+
* stream so you can show the conversation immediately. Pass `signal` to cancel on unmount. */
|
|
1064
|
+
async send(text: string, o: ChatSendOptions = {}): Promise<void> {
|
|
1065
|
+
const convId = await this.#ensure(o, text);
|
|
1066
|
+
o.onConversationId?.(convId);
|
|
1067
|
+
await this.#kc.queryStream(
|
|
1068
|
+
this.#agentId,
|
|
1069
|
+
{ corpus_ids: this.#corpusIds, query: text, conversation_id: convId,
|
|
1070
|
+
overrides: o.overrides, filter: o.filter, visual: o.visual },
|
|
1071
|
+
o,
|
|
1072
|
+
o.signal,
|
|
1073
|
+
);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
/** The conversation history (messages), once it exists. Empty page before the first send. */
|
|
1077
|
+
messages(q?: { limit?: number; cursor?: string }): Promise<Page<Message>> {
|
|
1078
|
+
if (!this.conversationId) return Promise.resolve({ items: [], next_cursor: null });
|
|
1079
|
+
return this.#kc.conversations.listMessages(this.conversationId, q);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1004
1083
|
// ---------------------------------------------------------------------------
|
|
1005
1084
|
// helpers
|
|
1006
1085
|
// ---------------------------------------------------------------------------
|